hw2csv, ou comment convertir des fichiers HeavyWeather en CSV

hw2csv est un tout petit programme qui permet de convertir des fichiers HeavyWeather (history.dat) en fichiers CSV. Je l’ai écrit pour pouvoir extraire quelques données issues d’une station météo “La Crosse”, à l’aide de la documentation disponible ici. C’est de la programmation à la tronçonneuse, mais ça fonctionne…

Captures d’écran

C’est un logiciel sans interface utilisateur (sous Windows, vous aurez droit à quelques boîtes de dialogue “Ouvrir”, “Enregistrer” que Windows crée tout seul): je n’ai donc pas de captures d’écran à fournir.

Téléchargement

Télécharger la source C

Télécharger les binaires Windows

Binaires Windows

Téléchargez hw2csv.zip puis exécutez hw2csv.exe. Vous devez posséder un fichier d’historique HeavyWeather pour que le programme serve à quelque chose…

Code source\

Téléchargez hw2csv.c, puis compilez-le (gcc -o hw2csv hw2csv.c, sous Windows rajoutez -lcomdlg), ou copiez le code ci-dessous:\

    /* 
    * This program is free software: you can redistribute it and/or modify
    * it under the terms of the GNU General Public License as published by
    * the Free Software Foundation, either version 3 of the License, or
    * (at your option) any later version.
    * 
    * This program is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    * GNU General Public License for more details.
    * 
    * You should have received a copy of the GNU General Public License
    * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #ifdef WIN32
    #include <windows.h>
    #include <fcntl.h>
    #include <io.h>
    #include <stdint.h>
    #endif
    #include <time.h>
    #include <dirent.h>

    #include <locale.h>

    int32_t readLong(FILE* f);
    float readFloat(FILE* f);
    short readShort(FILE* f);

    int main(int argc, char* argv[])
    {
    #ifndef WIN32
      if(argc < 2)
      {
         printf("Usage: hw2csv [history.dat file] [out.csv file]\n");
         return 1;
      }
    #endif
      FILE* in = NULL;
      setlocale(LC_ALL, "french");
    #ifdef WIN32
      if(argc < 2)
      {
         OPENFILENAME of;
         char FileName[MAX_PATH] = "";

         ZeroMemory(&of, sizeof(of));

         of.lStructSize = sizeof(of);
         of.hwndOwner = 0;
         of.lpstrFilter = "Fichier DAT\0*.dat\0Tous les fichiers (*.*)\0*.*\0";
         of.lpstrFile = FileName;
         of.lpstrTitle = "Ouvrir le fichier historique";
         of.nMaxFile = MAX_PATH;
         of.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
         of.lpstrDefExt = "dat";

         if(GetOpenFileName(&of))
         {
            in = fopen(FileName, "r");
         }
      }
      else
      {
         in = fopen(argv[1],"r");
      }
    #else
      in = fopen(argv[1],"r");
    #endif

      FILE* outV = NULL;
    #ifdef WIN32
      if(argc < 3)
      {
         OPENFILENAME ofn;
         char wfn[MAX_PATH] = "";

         ZeroMemory(&ofn, sizeof(ofn));

         ofn.lStructSize = sizeof(ofn);
         ofn.hwndOwner = 0;
         ofn.lpstrFilter = "Feuille CSV\0*.csv\0Tous les fichiers (*.*)\0*.*\0";
         ofn.lpstrFile = wfn;
         ofn.lpstrTitle = "Sous quel nom enregistrer le fichier?";
         ofn.nMaxFile = MAX_PATH;
         ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
         ofn.lpstrDefExt = "csv";

         if(GetSaveFileName(&ofn))
         {
            outV = fopen(wfn, "w");
         }
      }
      else
      {
         outV = fopen(argv[2], "w");     
      }
    #else
      if(argc >= 3)
         outV = fopen(argv[2], "w");
      else {
         printf("Manque l'argument fichier de sortie\n");
         return -1;
      }

    #endif
      
      if(in == NULL || outV == NULL)
      {
    #ifdef WIN32
      MessageBox(NULL,"Problème avec un fichier.","Info",MB_ICONINFORMATION);
    #else
      printf("Problème avec un fichier.\n");
    #endif
         if(outV != NULL) fclose(outV);
         if(in != NULL) fclose(in);
        return -1;
      }
    #ifdef WIN32
      setmode(fileno(in), _O_BINARY);
    #endif

      int32_t initValue = 0; //value that should always be 1 while we're reading valid HeavyWeather data
      int32_t timeStamp;
      float absPressure;
      float windSpeed;
      int32_t windDirection;
      float totalRainFall;
      float indoorTemp;
      float outdoorTemp;
      short indoorHumidity;
      short outdoorHumidity;
      char formatV[] = "%Y;%m;%d;%H:%M";  
      char timeV[30];
      char timePV[30];
      
      
      //CSV
      fprintf(outV,"Annee;Mois;Jour;Heure;Pression;ForceVent;DirectionVent;CumulPluie;TempInterieure;TempExterieure;HumiditeInt;HumiditeExt\n");
      
      //Let's go
      initValue = readLong(in);
      long int count = 0;
      while(initValue == 0x01)
      {
        timeStamp = readLong(in);
        timeStamp = timeStamp - (int32_t)2208988800; //for whatever reason, HeavyWeather does not begin on Jan 1, 1970...

        time_t tt = (time_t) timeStamp;
        strftime(timeV,30,formatV,localtime(&tt));

        absPressure = readFloat(in);
        windSpeed = readFloat(in);
        windDirection = readLong(in);
        char sWindDirection[4];
        
        switch(windDirection)
        {
          case 0:
               strcpy(sWindDirection,"N");
               break;
          case 1:
               strcpy(sWindDirection,"NNE");
               break;      
          case 2:
               strcpy(sWindDirection,"NE");
               break;
          case 3:
               strcpy(sWindDirection,"ENE");
               break;       
          case 4:
               strcpy(sWindDirection,"E");
               break;
          case 5:
               strcpy(sWindDirection,"ESE");
               break;      
          case 6:
               strcpy(sWindDirection,"SE");
               break;
          case 7:
               strcpy(sWindDirection,"SSE");
               break;
          case 8:
               strcpy(sWindDirection,"S");
               break;
          case 9:
               strcpy(sWindDirection,"SSO");
               break;      
          case 10:
               strcpy(sWindDirection,"SO");
               break;
          case 11:
               strcpy(sWindDirection,"OSO");
               break;       
          case 12:
               strcpy(sWindDirection,"O");
               break;
          case 13:
               strcpy(sWindDirection,"ONO");
               break;      
          case 14:
               strcpy(sWindDirection,"NO");
               break;
          case 15:
               strcpy(sWindDirection,"NNO");
               break;                 
        }
        totalRainFall = readFloat(in);
        indoorTemp = readFloat(in);
        outdoorTemp = readFloat(in);
        indoorHumidity = readShort(in);
        outdoorHumidity = readShort(in);
         
        fprintf(outV,"%s;%lf;%lf;%s;%lf;%lf;%lf;%d;%d\n",timeV,absPressure,windSpeed,sWindDirection,totalRainFall,indoorTemp,outdoorTemp,indoorHumidity,outdoorHumidity);
        
        initValue = readLong(in);
        count++;
      }
      fclose(in);
      fclose(outV);
    #ifdef WIN32
      char msg[300] = "Conversion effectuée. ";
      char cnt[50] = "";
      itoa(count, cnt, 10);
      strcat(msg, cnt);
      strcat(msg, " valeurs traitées.");
      MessageBox(NULL,msg,"Info",MB_ICONINFORMATION);
    #else
      printf("Conversion effectuée. Traitement de %ld valeurs.\n",count);
    #endif
      return 0;
    }

    int32_t readLong(FILE *f) {
      int32_t v;
      fread((void*)(&v), sizeof(v), 1, f);
      return v;
    }

    float readFloat(FILE *f) {
      float v;
      fread((void*)(&v), sizeof(v), 1, f);
      return v;
    }

    short readShort(FILE *f) {
      short v;
      fread((void*)(&v), sizeof(v), 1, f);
      return v;
    }