• Main Page
  • Data Structures
  • Files

oif.c

Go to the documentation of this file.
00001 /*
00002  * This file is part of Titan2Reader
00003  *
00004  * Copyright (C) 2006, Sebastien Judenherc <sebastien.judenherc@agecodagis.com>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00019  * USA
00020  *
00021  */
00022 
00023 #define _GNU_SOURCE
00024 
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <time.h>
00028 #include <ctype.h>
00029 #include <math.h>
00030 #include <errno.h>
00031 #include <unistd.h>
00032 #include <string.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 #include <dirent.h>
00037 #include <assert.h>
00038 #include <signal.h>
00039 #include <string.h>
00040 
00041 #include "common.h"
00042 
00043 #define MAX_FUZZYNESS (600) // 10 minutes
00044 #define MAX_SAGEDATA_AGE (4*86400) // 4 jours
00045 #define MAX_LONGINFOS_AGE (86400+100) // 1 jour
00046 #define MAX_LONGINFOS_AGE_TIMEOUT (10*86400+100) // 10 jours
00047 #define MAX_GPS_TOP_OLDNESS (86400+100) // 1 jour
00048 #define DISK_REMAINING_THRESHOLD (3*86400) // 3 jours
00049 #define POWER_REMAINING_THRESHOLD (3*86400) // 3 jours
00050 #define INTERNAL_BATTERY_MIN_LEVEL (6.0) // 6V
00051 #define INTERNAL_BATTERY_MAX_LEVEL (9.0) // 6V
00052 #define POWER_LEVEL_THRESHOLD (11.5) // 11.5V!
00053 #define REBOOT_DELAY (86400/2) // 1/2 jour
00054 
00055 #define MAX_STRING_LENGTH 64
00056 #define OSIRIS_ERROR_MESSAGES 20 // 10 !
00057 #define OSIRIS_ERROR_MESSAGE_LENGTH 255
00058 
00059 int omniMode=0;
00060 
00061 enum { TYPE_Y=1, TYPE_B, TYPE_T, TYPE_F, TYPE_S, TYPE_O, TYPE_D, TYPE_C, TYPE_H, TYPE_f, TYPE_G };
00062 
00063 int verboseMode=0; 
00064 int doGpsMap=0; 
00065 int doHtml=1; 
00066 int embedHtml=0; 
00067 char imagePrefix[256]; 
00068 int alertFlag=0; 
00069 
00070 char osirisErrorMessage[OSIRIS_ERROR_MESSAGES][OSIRIS_ERROR_MESSAGE_LENGTH+1];
00071 char osirisAlertFile[OSIRIS_ERROR_MESSAGE_LENGTH];
00072 char tileBaseName[OSIRIS_ERROR_MESSAGE_LENGTH];
00073 char osirisErrorFile[OSIRIS_ERROR_MESSAGE_LENGTH];
00074 char osirisShortInfoFile[OSIRIS_ERROR_MESSAGE_LENGTH];
00075 
00077 struct OsirisInformationField {
00078         char name[MAX_STRING_LENGTH];   
00079         int type;                       
00080         int verboseOnly;                
00081         int valid;                      
00082         union {                         
00083                 float f;                
00084                 int d;                  
00085                 char s[MAX_STRING_LENGTH];      
00086         } value;
00087 };
00088 
00089 int doTile=0; 
00090 
00091 struct ShortInfos {
00092         int comdError;
00093         int activeChannels;
00094         int digitLoad;
00095         int storageError;
00096         int storageRate;
00097         int storageMounted;
00098         int storageRemain;
00099         int storageDetected;
00100         int flashError;
00101         int flashRate;
00102         int flashMounted;
00103         int flashRemain;
00104         int flashDetected;
00105         int flash2storage;
00106         int digit2storage;
00107         int digit2flash;
00108         char missing[256];
00109         int gpsSats;
00110         time_t age;
00111         int valid;
00112 };
00113 
00115 struct MessageType {
00116         int32_t destination; // not used in oif.c
00117         int32_t hostid;      // not used in oif.c
00118 #define IFNAMSIZ        16
00119         char iface[IFNAMSIZ];
00120         int32_t gateway;
00121         unsigned char metric;
00122         unsigned char flag;
00123         time_t stamp; 
00124 #define STATNAMELEN 12
00125         char name[STATNAMELEN+1];
00126 #ifdef __CYGWIN__
00127         char dummy1;
00128         char dummy2;
00129         char dummy3;
00130         int64_t id __attribute__((packed));
00131 #else
00132         int64_t id;
00133 #endif
00134         char state[12];
00135 };
00136 
00137 struct ShortInfos myShi; 
00138 struct MessageType myMessage; 
00139 
00140 
00141 #include "oifdefine.c"
00142 
00143 struct OsirisAlert {
00144         char *key;
00145         time_t firstTime;
00146         char * message;
00147         int(*check)(void);
00148 };
00149 
00150 #include "oifalert.c"
00151 
00152 /*
00153  * read name.oif, name.oef, name.orf
00154  * build a web page: name.html
00155  * build the station image: name.gif (if gd is used)
00156  * build the gps image: namegps.gif (if gd is used)
00157  */
00158 
00161 void ReadShortInfos(void)
00162 {
00163         FILE *f;
00164         char tmps[64];
00165         char infos[12];
00166         struct stat st;
00167         int state;
00168         myShi.valid=0;
00169         // some sanity checks
00170         memset(&myShi,0,sizeof(struct ShortInfos));
00171         // special cases at 1 without info, these fields should be updated soon
00172         myShi.storageDetected=1;
00173         myShi.flashDetected=1;
00174 
00175         if (gpsd_SystemTime.valid==0)
00176         {
00177                 if (acquisit_CorrectedTime.valid)
00178                 {
00179                         gpsd_SystemTime.valid=1;
00180                         gpsd_SystemTime.value.d=acquisit_CorrectedTime.value.d;
00181                 }
00182                 if ((diskmgr_LastAcquisitCorrectedTime.valid)&&
00183                                 (diskmgr_LastAcquisitCorrectedTime.value.d>0))
00184                 {
00185                         gpsd_SystemTime.valid=1;
00186                         gpsd_SystemTime.value.d=diskmgr_LastAcquisitCorrectedTime.value.d;
00187                 }
00188         }
00189 
00190         if (gpsd_SystemTime.valid)
00191         {
00192                 myShi.age=abs(time(NULL)-gpsd_SystemTime.value.d);
00193         }
00194         // first fill the shi according to the oif
00195 
00196         /*
00197         int activeChannels;
00198         int storageRemain;
00199         int flashRemain;
00200         int flash2storage;
00201         int digit2storage;
00202         int digit2flash;
00203         char missing[256];
00204         int gpsSats;
00205         */
00206         // acquisit:
00207         if (acquisit_DspRate.valid)
00208         {
00209                 myShi.digitLoad=(int)(acquisit_DspRate.value.f+0.5);
00210         }
00211         else
00212         {
00213                 myShi.digitLoad=-1;
00214         }
00215         // compter les canaux actifs
00216         myShi.activeChannels=0;
00217 #define COUNT(i) { if (acquisit_Fs##i.value.d>0) { myShi.activeChannels++; } }
00218         COUNT(0); COUNT(1); COUNT(2); COUNT(3); COUNT(4); COUNT(5);
00219         COUNT(6); COUNT(7); COUNT(8); COUNT(9); COUNT(10); COUNT(11);
00220         COUNT(12); COUNT(13); COUNT(14); COUNT(15); COUNT(16); COUNT(17);
00221         COUNT(18); COUNT(19); COUNT(20); COUNT(21); COUNT(22); COUNT(23);
00222         // diskmgr:
00223         myShi.storageDetected=(strncmp(diskmgr_StorageStatus.value.s,"detected",8)==0)?1:0;
00224         myShi.flashDetected=(strncmp(diskmgr_FlashStatus.value.s,"detected",8)==0)?1:0;
00225 
00226         myShi.storageError=(strstr(diskmgr_StorageStatus.value.s,"/error")==0)?0:1;
00227         myShi.flashError=(strstr(diskmgr_FlashStatus.value.s,"/error")==0)?0:1;
00228 
00229         myShi.storageMounted=(strstr(diskmgr_StorageStatus.value.s,"/mounted")==0)?0:1;
00230         myShi.flashMounted=(strstr(diskmgr_FlashStatus.value.s,"/mounted")==0)?0:1;
00231 
00232         myShi.storageRate=(int)(diskmgr_StorageRate.value.f+0.5);
00233         myShi.flashRate=(int)(diskmgr_FlashRate.value.f+0.5);
00234 
00235         myShi.storageRemain=diskmgr_StorageRemainingTime.value.d;
00236 
00237         if (diskmgr_Record.value.d==1)
00238         {
00239                 if ((diskmgr_ForceStorageWrite.value.d==1)||(diskmgr_DirectDisk.value.d==1))
00240                 {
00241                         myShi.digit2storage=1;
00242                 }
00243                 else
00244                 {
00245                         myShi.digit2flash=1;
00246                         if (diskmgr_Flush.value.d==1)
00247                         {
00248                                 myShi.flash2storage=1;
00249                         }
00250                 }
00251         }
00252 
00253         // then try to overload the oif/shi
00254         // comd:
00255         myShi.comdError+=comd_MessageFlag.value.d&0x1;
00256 
00257         if (osirisShortInfoFile[0]!=0)
00258         {
00259                 strcpy(tmps,osirisShortInfoFile);
00260                 if (comd_Hostid.valid==0)
00261                 {
00262                         if (getenv("HOSTID")!=NULL)
00263                         {
00264                                 strcpy(comd_Hostid.value.s,getenv("HOSTID"));
00265                         }
00266                 }
00267         }
00268         else
00269         {
00270                 sprintf(tmps,"/tmp/shi/%s",comd_Hostid.value.s);
00271         }
00272 
00273         // read the timestamp of the shi file
00274         stat(tmps,&st);
00275 
00276         // if the shi file is too old, remove it
00277         if (time(NULL)-st.st_mtime>300)
00278         {
00279                 unlink(tmps);
00280         }
00281         else
00282         {
00283                 myShi.age=abs(time(NULL)-st.st_mtime);
00284         }
00285 
00286 
00287         f=fopen(tmps,"rb");
00288         if (f==NULL)
00289         {
00290                 PrintDebug("%s (%s): %m\n",tmps,comd_Hostid.value.s);
00291                 return;
00292         }
00293         if (fread(&myMessage,sizeof(struct MessageType),1,f)!=1)
00294         {
00295                 fclose(f);
00296                 PrintDebug("read error on %s (%s): %m\n",tmps,comd_Hostid.value.s);
00297                 return;
00298         }
00299         memcpy(infos,myMessage.state,12);
00300         fclose(f);
00301         myShi.valid=1;
00302 
00303         myShi.comdError+=myMessage.flag&1;
00304 
00305         // analyse the shi
00306 
00307         myShi.activeChannels=infos[0]&0xff;
00308         myShi.digitLoad=(int)(100.*35.*(exp((double)(infos[1]&0xff)/35.)-1.)/(24*2000));
00309         myShi.gpsSats=gpsd_GpsNasa.value.d=(infos[8]&0x7);
00310         switch (infos[6]&0x3)
00311         {
00312                 case 2 /*GPS_SYNC*/:
00313                         sprintf(gpsd_GpsState.value.s,"sync");
00314                         gpsd_OnOff.value.d=1;
00315                         break;
00316                 case 1 /*GPS_WAIT*/:
00317                         sprintf(gpsd_GpsState.value.s,"waiting");
00318                         gpsd_OnOff.value.d=1;
00319                         break;
00320                 case 0 /*GPS_OFF*/:
00321                         gpsd_OnOff.value.d=0;
00322                         gpsd_GpsNasa.value.d=0;
00323                         break;
00324         }
00325 
00326         if ((infos[6]>>2)&0x2)
00327         {
00328                 myShi.digit2storage=1;
00329         }
00330 
00331         if ((infos[6]>>2)&0x1)
00332         {
00333                 myShi.digit2flash=1;
00334         }
00335 
00336         if ((infos[6]>>4)&0x1)
00337         {
00338                 myShi.flash2storage=1;
00339         }
00340         myShi.storageRate=infos[3]&0xff;
00341         myShi.flashRate=infos[4]&0xff;
00342         // flash state
00343         state=(infos[5]>>4)&0xff;
00344         switch (state&0x3)
00345         {
00346                 case 0:
00347                         break;
00348                 case 3:
00349                         myShi.flashError=1;
00350                         break;
00351                 case 2:
00352                         myShi.flashMounted=1;
00353                         myShi.flashDetected=1;
00354                         break;
00355                 case 1:
00356                         myShi.flashDetected=1;
00357                         break;
00358         }
00359 
00360         // storage state
00361         state=(infos[5]>>2)&0xff;
00362         switch (state&0x3)
00363         {
00364                 case 0:
00365                         break;
00366                 case 3:
00367                         myShi.storageError=1;
00368                         break;
00369                 case 2:
00370                         myShi.storageMounted=1;
00371                         myShi.storageDetected=1;
00372                         break;
00373                 case 1:
00374                         myShi.storageDetected=1;
00375                         break;
00376         }
00377 
00378         /*
00379         int storageError;
00380         int storageRate; 
00381         int storageMounted;
00382         int storageRemain;
00383         int storageDetected;
00384         int flashError;
00385         int flashRate;
00386         int flashMounted;
00387         int flashRemain;
00388         int flashDetected;
00389         int flash2storage;
00390         int digit2storage;
00391         int digit2flash;
00392         char missing[256];
00393         time_t age;
00394 */
00395 }
00396 
00397 #ifdef USE_GD
00398 
00399 #include <gd.h>
00400 #include <gdfontmb.h>
00401 #include <gdfontt.h>
00402 #include <gdfonts.h>
00403 
00404 #define MAX_RTD_DELAY 60
00405 
00406 // write the GPS map
00407 void WriteGpsMap(FILE *fout)
00408 {
00409 
00410 #define XMAX 240
00411 #define YMAX 240
00412 #define XOFFSET 25
00413 #define YOFFSET 25
00414 #define MAX_SAT 64
00415         int az[MAX_SAT], el[MAX_SAT], sn[MAX_SAT];
00416         int i;
00417         int white,black,grey,green;
00418         int x,y;
00419         char line[1024];
00420         gdPoint points[2];
00421         gdImagePtr im; 
00422 
00423         // init
00424         for (i=0; i<MAX_SAT; i++)
00425         {
00426                 az[i]=el[i]=sn[i]=-1;
00427         }
00428         // allouer la m?moire ? l'image
00429         im = gdImageCreate(XMAX, YMAX);
00430         // déterminer les couleurs
00431         white = gdImageColorAllocate(im, 255, 255, 255);
00432         black = gdImageColorAllocate(im, 0, 0, 0);
00433         green = gdImageColorAllocate(im, 0, 0, 255);
00434         grey = gdImageColorAllocate(im, 192, 192, 192);
00435 
00436         // d'abord la cible: 2 cerlces
00437         x=1+XOFFSET/2+(XMAX-XOFFSET)/2;
00438         y=1+YOFFSET/2+(YMAX-YOFFSET)/2;
00439         gdImageArc(im, x, y,
00440                         (XMAX-XOFFSET)+1, (XMAX-XOFFSET)+1,
00441                         0, 360, black);
00442         gdImageArc(im, x, y,
00443                         (XMAX-XOFFSET)/2, (XMAX-XOFFSET)/2,
00444                         0, 360, black);
00445 
00446         points[0].x=x; points[0].y=YMAX-YOFFSET/2;
00447         points[1].x=x; points[1].y=YOFFSET/2;
00448         gdImageOpenPolygon(im, points, 2, black);
00449         points[0].y=y; points[0].x=XMAX-XOFFSET/2;
00450         points[1].y=y; points[1].x=XOFFSET/2;
00451         gdImageOpenPolygon(im, points, 2, black);
00452 
00453         // les points cardinaux
00454         line[1]=0;
00455         line[0]='W';
00456         gdImageString(im, gdFontGetSmall(), 4, y-7,
00457                         (unsigned char *)line,black);
00458         line[0]='E';
00459         gdImageString(im, gdFontGetSmall(), XMAX-XOFFSET/2+3, y-7,
00460                         (unsigned char *)line,black);
00461         line[0]='N';
00462         gdImageString(im, gdFontGetSmall(), x-2, 0,
00463                         (unsigned char *)line,black);
00464         line[0]='S';
00465         gdImageString(im, gdFontGetSmall(), x-2, YMAX-YOFFSET/2,
00466                         (unsigned char *)line,black);
00467 
00468 #define PROCESS_ONE_SAT0(index) \
00469         if (gpsd_Sat0##index##El.valid>0) \
00470         { \
00471                 el[index]=gpsd_Sat0##index##El.value.d; \
00472                 az[index]=gpsd_Sat0##index##Az.value.d; \
00473                 sn[index]=gpsd_Sat0##index##Sn.value.d; \
00474         }
00475 #define PROCESS_ONE_SAT(index) \
00476         if (gpsd_Sat##index##El.valid>0) \
00477         { \
00478                 el[index]=gpsd_Sat##index##El.value.d; \
00479                 az[index]=gpsd_Sat##index##Az.value.d; \
00480                 sn[index]=gpsd_Sat##index##Sn.value.d; \
00481         }
00482         PROCESS_ONE_SAT0(0); PROCESS_ONE_SAT0(1); PROCESS_ONE_SAT0(2); PROCESS_ONE_SAT0(3);
00483         PROCESS_ONE_SAT0(4); PROCESS_ONE_SAT0(5); PROCESS_ONE_SAT0(6); PROCESS_ONE_SAT0(7);
00484         PROCESS_ONE_SAT0(8); PROCESS_ONE_SAT0(9);
00485         PROCESS_ONE_SAT(10); PROCESS_ONE_SAT(11); PROCESS_ONE_SAT(12); PROCESS_ONE_SAT(13);
00486         PROCESS_ONE_SAT(14); PROCESS_ONE_SAT(15); PROCESS_ONE_SAT(16); PROCESS_ONE_SAT(17);
00487         PROCESS_ONE_SAT(18); PROCESS_ONE_SAT(19);
00488         PROCESS_ONE_SAT(20); PROCESS_ONE_SAT(21); PROCESS_ONE_SAT(22); PROCESS_ONE_SAT(23);
00489         PROCESS_ONE_SAT(24); PROCESS_ONE_SAT(25); PROCESS_ONE_SAT(26); PROCESS_ONE_SAT(27);
00490         PROCESS_ONE_SAT(28); PROCESS_ONE_SAT(29);
00491         PROCESS_ONE_SAT(30); PROCESS_ONE_SAT(31);
00492         // pour chaque satellite
00493         for (i=0; i<MAX_SAT; i++)
00494         {
00495                 // si az!=-1
00496                 if (az[i]>0)
00497                 {
00498                         float a;
00499                         a=M_PI*(90.-(float)az[i])/180.;
00500                         // calculer x et y
00501                         x=(int)((float)(XMAX-XOFFSET)*(90.-(float)el[i])*cos(a)/90.);
00502                         y=(int)((float)(XMAX-XOFFSET)*(90.-(float)el[i])*sin(a)/90.);
00503                         x+=(XMAX-XOFFSET);
00504                         y=(XMAX-XOFFSET)-y;
00505                         x/=2;
00506                         y/=2;
00507                         x+=gdFontGetSmall()->h;
00508                         y+=gdFontGetSmall()->w;
00509                         //fprintf(stderr,"%02d: %d,%d %d\n",i,az[i],el[i],sn[i]);
00510                         // dessiner le texte en couleur
00511                         sprintf(line,"%02d",i);
00512                         gdImageString(im, gdFontGetSmall(), x, y,
00513                                         (unsigned char *)line,
00514                                         (sn[i]>0)?green:grey);
00515                 // finsi
00516                 }
00517         // finpour
00518         }
00519 
00520         /* Write GIF */
00521         gdImageGif(im, fout);
00522         gdImageDestroy(im);
00523 }
00524 
00525 // write the tile
00526 void WriteTile(FILE *fout)
00527 {
00528         gdImagePtr im;
00529         int white,back,black,red,grey;
00530         int delay;
00531         int color;
00532         int d,h,m,s;
00533         char tmp[32];
00534 
00535         void DigitBox(int active, int load)
00536         {
00537                 char ttmp[16];
00538                 gdPoint p[5];
00539                 if (active>=0)
00540                 {
00541                         sprintf(ttmp,"%d",active);
00542                         gdImageString(im, gdFontGetSmall(),
00543                                         10,
00544                                         50,
00545                                         (unsigned char *)ttmp, black);
00546                 }
00547                 if (load>=0)
00548                 {
00549                         sprintf(ttmp,"%d%%",load);
00550                 }
00551                 else
00552                 {
00553                         strcpy(ttmp,"###");
00554                 }
00555                 gdImageString(im, gdFontGetSmall(),
00556                                 10,
00557                                 70,
00558                                 (unsigned char *)ttmp, black);
00559                 p[0].x= 5;      p[0].y=47;
00560                 p[1].x=35;      p[1].y=47;
00561                 p[2].x=35;      p[2].y=85;
00562                 p[3].x= 5;      p[3].y=85;
00563                 p[4].x= 5;      p[4].y=47;
00564                 gdImagePolygon(im, p, 5, black);
00565                 p[0].x= 7;      p[0].y=49;
00566                 p[1].x=33;      p[1].y=49;
00567                 p[2].x=33;      p[2].y=64;
00568                 p[3].x= 7;      p[3].y=64;
00569                 p[4].x= 7;      p[4].y=49;
00570                 gdImagePolygon(im, p, 5, black);
00571                 p[0].x= 7;      p[0].y=68;
00572                 p[1].x=33;      p[1].y=68;
00573                 p[2].x=33;      p[2].y=83;
00574                 p[3].x= 7;      p[3].y=83;
00575                 p[4].x= 7;      p[4].y=68;
00576                 gdImagePolygon(im, p, 5, black);
00577         }
00578 
00579         void DiskBox(int flash, int error, int mounted, int detected,
00580                         int remain, float rate)
00581         {
00582                 gdPoint p[5],pin[5];
00583                 int delta;
00584                 int cm;
00585                 if (flash)
00586                 {
00587                         p[0].x=80;      p[0].y=150;
00588                         p[1].x=80;      p[1].y=70;
00589                         p[2].x=115;     p[2].y=70;
00590                         p[3].x=115;     p[3].y=150;
00591                         p[4].x=80;      p[4].y=150;
00592                 }
00593                 else
00594                 {
00595                         p[0].x=152;      p[0].y=150;
00596                         p[1].x=152;      p[1].y=25;
00597                         p[2].x=187;      p[2].y=25;
00598                         p[3].x=187;      p[3].y=150;
00599                         p[4].x=152;      p[4].y=150;
00600                 }
00601                 memcpy(pin,p,sizeof(p));
00602                 delta=0.01*rate*(p[0].y-p[1].y);
00603                 pin[1].y=pin[2].y=p[0].y-delta;
00604 
00605                 cm=grey;
00606                 if (mounted)
00607                 {
00608                         cm=black;
00609                 }
00610                 if (error)
00611                 {
00612                         cm=red;
00613                 }
00614 
00615                 gdImageSetThickness(im, 3);
00616                 gdImagePolygon(im, p, 5, cm);
00617 
00618                 if (flash || detected)
00619                 {
00620                         gdImageSetThickness(im, 1);
00621                         gdImageFilledPolygon(im, pin, 5, cm);
00622                 }
00623                 gdImageSetThickness(im, 1);
00624                 if ((flash==0)&&(detected!=0))
00625                 {
00626                         char ttmp[16];
00627                         sprintf(ttmp,"%dd",remain/86400);
00628                         cm=white;
00629                         if (diskmgr_StoragePolicy.valid)
00630                         {
00631                                 if (0!=strcasecmp(diskmgr_StoragePolicy.value.s,"cycle"))
00632                                 {
00633                                         if (remain<DISK_REMAINING_THRESHOLD)
00634                                         {
00635                                                 cm=red;
00636                                         }
00637                                 }
00638                         }
00639                         gdImageString(im, gdFontGetSmall(),
00640                                         p[0].x+10, p[0].y-15,
00641                                         (unsigned char *)ttmp, cm);
00642                 }
00643         }
00644 
00645         void BatteryLevel(float voltage, int erh, char *state)
00646         {
00647                 int i,color;
00648                 gdPoint p[5];
00649                 int cx,cy,w;
00650                 int ascale=90;
00651                 int vmin=10;
00652                 int vmax=14;
00653                 int a;
00654                 float s,c;
00655                 char tmp[16];
00656                 p[0].x= 5;      p[0].y=90;
00657                 p[1].x=75;      p[1].y=90;
00658                 p[2].x=75;      p[2].y=120;
00659                 p[3].x= 5;      p[3].y=120;
00660                 p[4].x= 5;      p[4].y=90;
00661                 gdImagePolygon(im, p, 5, black);
00662                 cx=1+((2*p[1].x)/3+p[0].x)/2;
00663                 w=2*(p[2].y-p[1].y);
00664                 cy=p[2].y;
00665 
00666                 p[0].x=(2*p[1].x)/3;
00667                 p[0].y=p[1].y;
00668                 p[1].x=p[0].x;
00669                 p[1].y=p[2].y;
00670                 gdImagePolygon(im, p, 2, black);
00671 
00672                 gdImageSetThickness(im, 2);
00673                 gdImageArc(im, cx, cy, w, w, 270-ascale/2, 270+ascale/2, black);
00674                 for (i=vmin; i<=vmax; i++)
00675                 {
00676                         a=((i-vmin)*ascale)/(vmax-vmin)-ascale/2;
00677                         s=sin((float)a*M_PI/180.)*w/2.1;
00678                         c=cos((float)a*M_PI/180.)*w/2.1;
00679 
00680                         p[0].x=cx+0.8*s;
00681                         p[0].y=cy-0.8*c;
00682 
00683                         p[1].x=cx+s;
00684                         p[1].y=cy-c;
00685                         gdImagePolygon(im, p, 2, black);
00686                 }
00687                 color=grey;
00688                 a=((voltage-(float)vmin)*(float)ascale)/(float)(vmax-vmin)-ascale/2.;
00689                 if (voltage>vmax)
00690                 {
00691                         a=((vmax-(float)vmin)*(float)ascale)/(float)(vmax-vmin)-ascale/2.;
00692                 }
00693                 if (voltage<vmin)
00694                 {
00695                         a=((vmin-(float)vmin)*(float)ascale)/(float)(vmax-vmin)-ascale/2.;
00696                 }
00697                 s=sin((float)a*M_PI/180.)*w/2.1;
00698                 c=cos((float)a*M_PI/180.)*w/2.1;
00699                 p[0].x=cx;
00700                 p[0].y=cy;
00701 
00702                 p[1].x=cx+0.8*s;
00703                 p[1].y=cy-0.8*c;
00704 
00705 
00706                 if (strstr(state,"empty"))
00707                 {
00708                         color=black;
00709                 }
00710                 if (strstr(state,"critical"))
00711                 {
00712                         color=red;
00713                 }
00714                 if (CheckBatteryLevel())
00715                 {
00716                         color=red;
00717                 }
00718                 gdImagePolygon(im, p, 2, color);
00719                 sprintf(tmp,"%3.1fV",voltage);
00720                 gdImageString(im, gdFontGetSmall(),cx-15,cy-15, (unsigned char *)tmp, color);
00721 
00722                 p[0].x=53;      p[0].y=100;
00723                 p[1].x=72;      p[1].y=100;
00724                 p[2].x=68;      p[2].y=98;
00725                 p[3].x=68;      p[3].y=102;
00726                 p[4].x=72;      p[4].y=100;
00727 
00728                 if (strstr(state,"charging"))
00729                 {
00730                         p[0].x=53;      p[0].y=105;
00731                         p[1].x=72;      p[1].y=94;
00732                         p[2].x=67;      p[2].y=94;
00733                         p[3].x=70;      p[3].y=98;
00734                         p[4].x=72;      p[4].y=94;
00735                 }
00736                 if (strstr(state,"discharging"))
00737                 {
00738                         p[0].x=53;      p[0].y=94;
00739                         p[1].x=72;      p[1].y=105;
00740                         p[2].x=67;      p[2].y=105;
00741                         p[3].x=71;      p[3].y=101;
00742                         p[4].x=72;      p[4].y=105;
00743                 }
00744                 if (erh>0)
00745                 {
00746                         gdImagePolygon(im, p, 5, black);
00747                         gdImageSetThickness(im, 1);
00748                         if (erh>96)
00749                         {
00750                                 color=black;
00751                                 if (erh/24>30)
00752                                 {
00753                                         sprintf(tmp,">30d");
00754                                 }
00755                                 else
00756                                 {
00757                                         sprintf(tmp,"%dd",erh/24);
00758                                 }
00759                         }
00760                         else
00761                         {
00762                                 color=red;
00763                                 sprintf(tmp,"%dh",erh);
00764                         }
00765                         gdImageString(im, gdFontGetSmall(),52,cy-15, (unsigned char *)tmp, color);
00766                 }
00767 
00768         }
00769 
00770         void GpsBox(char *state, int number, int pulseAge)
00771         {
00772                 int delta,bc;
00773                 gdPoint p[5],pin[5];
00774 
00775                 p[0].x=5;       p[0].y=125;
00776                 p[1].x=5;       p[1].y=150;
00777                 p[2].x=75;      p[2].y=150;
00778                 p[3].x=75;      p[3].y=125;
00779                 p[4].x=5;       p[4].y=125;
00780                 memcpy(pin,p,sizeof(p));
00781                 if (number>4)
00782                 {
00783                         number=4;
00784                 }
00785                 delta=number*(p[2].x-p[1].x);
00786                 delta/=4;
00787                 pin[2].x=pin[3].x=p[0].x+delta;
00788 
00789                 gdImageFilledPolygon(im, pin, 5, grey);
00790 
00791                 bc=back;
00792                 if (0!=strstr(state,"sync"))
00793                 {
00794                         bc=black;
00795                 }
00796                 if (0!=strstr(state,"waiting"))
00797                 {
00798                         bc=grey;
00799                 }
00800                 if (
00801                                 (0!=strstr(state,"ERROR"))||
00802                                 (0!=strstr(state,"error"))
00803                                 )
00804                 {
00805                         bc=red;
00806                 }
00807                 if (bc!=back)
00808                 {
00809                         gdImageSetThickness(im, 3);
00810                 }
00811                 else
00812                 {
00813                         bc=black;
00814                 }
00815                 gdImagePolygon(im, p, 5, bc);
00816                 gdImageSetThickness(im, 1);
00817 
00818                 bc=black;
00819                 if (pulseAge>MAX_GPS_TOP_OLDNESS)
00820                 {
00821                         bc=red;
00822                 }
00823                 if (gpsd_GpsNsav.valid)
00824                 {
00825                         gdImageString(im, gdFontGetSmall(),25,132, (unsigned char *)"GPS", bc);
00826                 }
00827                 else
00828                 {
00829                         gdImageString(im, gdFontGetSmall(),25,132, (unsigned char *)"TIME", bc);
00830                 }
00831         }
00832 
00833         void Arrow(int x0, int y0, int len, int fc)
00834         {
00835                 gdPoint p[8];
00836                 p[0].x=x0;              p[0].y=y0;
00837                 p[1].x=x0+len-8;        p[1].y=y0;
00838                 p[2].x=x0+len-8;        p[2].y=y0-6;
00839                 p[3].x=x0+len;          p[3].y=y0+6;
00840                 p[4].x=x0+len-8;        p[4].y=y0+18;
00841                 p[5].x=x0+len-8;        p[5].y=y0+12;
00842                 p[6].x=x0;              p[6].y=y0+12;
00843                 p[7].x=x0;              p[7].y=y0;
00844                 gdImageFilledPolygon(im, p, 8, fc);
00845                 gdImagePolygon(im, p, 8, black);
00846         }
00847 
00848         void LastMsgBox(int delta)
00849         {
00850                 gdPoint p[5],pin[5];
00851                 if (delta>MAX_RTD_DELAY)
00852                 {
00853                         delta=MAX_RTD_DELAY;
00854                 }
00855                 p[0].x=5;       p[0].y=6;
00856                 p[1].x=40;      p[1].y=6;
00857                 p[2].x=40;      p[2].y=16;
00858                 p[3].x=5;       p[3].y=16;
00859                 p[4].x=5;       p[4].y=6;
00860                 memcpy(pin,p,sizeof(p));
00861 
00862                 delta*=(p[1].x-p[0].x);
00863                 delta/=MAX_RTD_DELAY;
00864                 pin[1].x=pin[2].x=p[0].x+delta;
00865 
00866                 gdImageFilledPolygon(im, pin, 5, grey);
00867                 gdImagePolygon(im, p, 5, black);
00868         }
00869 
00870         void ErrorBox(struct ShortInfos *s)
00871         {
00872                 char tmp[64];
00873                 if ((s->flashError)||(s->storageError)||(s->comdError))
00874                 {
00875                         strcpy(tmp,"ERROR");
00876                         color=red;
00877                 }
00878                 else
00879                 {
00880                         strcpy(tmp,"No HW error");
00881                         color=black;
00882                 }
00883                 gdImageString(im, gdFontGetSmall(), 50,   25, (unsigned char *)tmp, color);
00884                 if (access(".warnparameters",R_OK)==0)
00885                 {
00886                         strcpy(tmp,"Check parameters!");
00887                         gdImageString(im, gdFontGetSmall(), 50,   35,
00888                                         (unsigned char *)tmp, red);
00889                 }
00890         }
00891 
00892         // start of main code
00893 
00894         im = gdImageCreate(192, 155);
00895 
00896         if (myShi.valid==1)
00897         {
00898                 if (alertFlag==0)
00899                 {
00900                         if (myShi.age<90)
00901                         {
00902                                 back=gdImageColorAllocate(im, 250, 250, 250);
00903                         }
00904                         else
00905                         {
00906                                 back=gdImageColorAllocate(im, 210, 210, 210);
00907                         }
00908                 }
00909                 else
00910                 {
00911                         back=gdImageColorAllocate(im, 255, 192, 192);
00912                 }
00913         }
00914         else
00915         {
00916                 if (alertFlag==0)
00917                 {
00918                         back=gdImageColorAllocate(im, 210, 210, 210);
00919                 }
00920                 else
00921                 {
00922                         back=gdImageColorAllocate(im, 255, 192, 192);
00923                 }
00924         }
00925         black=gdImageColorAllocate(im, 92, 92, 92);
00926         white=gdImageColorAllocate(im, 0, 0, 0);
00927         red=gdImageColorAllocate(im, 220, 0, 0);
00928         grey=gdImageColorAllocate(im, 128, 128, 128);
00929 
00930         if (gpsd_SystemTime.valid)
00931         {
00932                 delay=abs(time(NULL)-gpsd_SystemTime.value.d);
00933                 d=delay/86400;
00934                 delay-=d*86400;
00935                 h=delay/3600;
00936                 delay-=h*3600;
00937                 m=delay/60;
00938                 delay-=m*60;
00939                 s=delay;
00940                 if (d<1)
00941                 {
00942                         sprintf(tmp,"Info: %2d:%02d:%02d",h,m,s);
00943                 }
00944                 else
00945                 {
00946                         sprintf(tmp,"Info:%2dd %02d:%02d'",d,h,m);
00947                 }
00948 
00949                 if ((time(NULL)-gpsd_SystemTime.value.d)>10800)
00950                 {
00951                         color=red;
00952                 }
00953                 else
00954                 {
00955                         color=black;
00956                 }
00957         }
00958         else
00959         {
00960                 strcpy(tmp,"Info: bad OIF");
00961                 color=red;
00962         }
00963         gdImageString(im, gdFontGetSmall(), 48,  5, (unsigned char *)tmp, color);
00964 
00965         if (diskmgr_LastAcquisitCorrectedTime.valid)
00966         {
00967                 delay=abs(time(NULL)-diskmgr_LastAcquisitCorrectedTime.value.d);
00968                 d=delay/86400;
00969                 delay-=d*86400;
00970                 h=delay/3600;
00971                 delay-=h*3600;
00972                 m=delay/60;
00973                 delay-=m*60;
00974                 s=delay;
00975                 if (d<1)
00976                 {
00977                         sprintf(tmp,"Data: %2d:%02d:%02d",h,m,s);
00978                 }
00979                 else
00980                 {
00981                         sprintf(tmp,"Data:%2dd %02d:%02d'",d,h,m);
00982                 }
00983 
00984                 if ((time(NULL)-diskmgr_LastAcquisitCorrectedTime.value.d)>10800)
00985                 {
00986                         color=red;
00987                 }
00988                 else
00989                 {
00990                         color=black;
00991                 }
00992         }
00993         else
00994         {
00995                 strcpy(tmp,"Data: bad OIF");
00996                 color=red;
00997         }
00998         if (
00999                         (0!=strcasecmp("MYKERINOS-R",sysd_OsirisModel.value.s))&&
01000                         (0!=strcasecmp("MYKERINOSR",sysd_OsirisModel.value.s))
01001            )
01002         {
01003                 gdImageString(im, gdFontGetSmall(), 48, 15, (unsigned char *)tmp, color);
01004         }
01005 
01006 
01007         gdImageString(im, gdFontGetSmall(),
01008                         144, 5, (unsigned char *)comd_Hostid.value.s, black);
01009 
01010         gdImageString(im, gdFontGetMediumBold(),
01011                         5,   17, (unsigned char *)comd_StationName.value.s, black);
01012 
01013         if (strcmp(tileBaseName,comd_StationName.value.s))
01014         {
01015                 gdImageString(im, gdFontGetMediumBold(),
01016                                 5,   30,
01017                                 (unsigned char *)tileBaseName, black);
01018         }
01019         ErrorBox(&myShi);
01020 
01021         LastMsgBox(myShi.age);
01022 
01023         if (
01024                         (0!=strcasecmp("MYKERINOS-R",sysd_OsirisModel.value.s))&&
01025                         (0!=strcasecmp("MYKERINOSR",sysd_OsirisModel.value.s))
01026            )
01027         {
01028                 DigitBox(myShi.activeChannels, myShi.digitLoad);
01029 
01030                 DiskBox(0, myShi.storageError, myShi.storageMounted,
01031                                 myShi.storageDetected,
01032                                 myShi.storageRemain, myShi.storageRate);
01033                 DiskBox(1, myShi.flashError, myShi.flashMounted,
01034                                 myShi.flashDetected,
01035                                 0, myShi.flashRate);
01036                 Arrow(120, 100, 27, myShi.flash2storage?grey:back);
01037                 Arrow(40, 50,107, myShi.digit2storage?grey:back);
01038                 Arrow(40, 70, 35, myShi.digit2flash?grey:back);
01039 
01040                 GpsBox(gpsd_GpsState.value.s, gpsd_GpsNasa.value.d,
01041                                 gpsd_SystemTime.value.d-gpsd_LastTimeSent.value.d);
01042         }
01043 
01044         if (sysd_ExtBat.valid)
01045         {
01046                 if (sysd_BattRemaining.valid==0)
01047                 {
01048                         sysd_BattRemaining.value.d=-1;
01049                 }
01050                 BatteryLevel(sysd_ExtBat.value.f, sysd_BattRemaining.value.d, sysd_BattState.value.s);
01051         }
01052 
01053         gdImageGif(im, fout);
01054         gdImageDestroy(im);
01055 }
01056 
01057 #endif
01058 
01062 int ReadField(char *line)
01063 {
01064         int i;
01065         char name[MAX_STRING_LENGTH];
01066         char value[MAX_STRING_LENGTH];
01067         // read the name of this field
01068         if (2!=sscanf(line,"%63s %63s",name,value))
01069         {
01070                 return(-1);
01071         }
01072         // ignore some fields
01073         if (!strncasecmp(name,"comd_Node",strlen("comd_Node"))) return(0);
01074 
01075         // look for the field in the table
01076         for (i=0; OIFList[i]!=NULL; i++)
01077         {
01078                 // if found
01079                 if (strcasecmp(OIFList[i]->name,name)==0)
01080                 {
01081                         // read the value according to the type of the field
01082                         switch (OIFList[i]->type)
01083                         {
01084                                 // boolean
01085                                 case TYPE_Y:
01086                                 case TYPE_O:
01087                                 case TYPE_B:
01088                                         // look for a yes/no/true/false... keyword
01089                                         if (
01090                                                         (strcasecmp(value,"1")==0)||
01091                                                         (strcasecmp(value,"ok")==0)||
01092                                                         (strcasecmp(value,"on")==0)||
01093                                                         (strcasecmp(value,"yes")==0)||
01094                                                         (strcasecmp(value,"true")==0)
01095                                            )
01096                                         {
01097                                                 OIFList[i]->value.d=1;
01098                                                 OIFList[i]->valid=1;
01099                                         }
01100                                         if (
01101                                                         (strcasecmp(value,"0")==0)||
01102                                                         (strcasecmp(value,"error")==0)||
01103                                                         (strcasecmp(value,"off")==0)||
01104                                                         (strcasecmp(value,"no")==0)||
01105                                                         (strcasecmp(value,"false")==0)
01106                                            )
01107                                         {
01108                                                 OIFList[i]->value.d=0;
01109                                                 OIFList[i]->valid=1;
01110                                         }
01111                                         // if we are there, we did not find a matching keyword
01112                                         break;
01113                                 case TYPE_D:
01114                                         if (1==sscanf(value,"%d",&(OIFList[i]->value.d)))
01115                                         {
01116                                                 OIFList[i]->valid=1;
01117                                         }
01118                                         break;
01119                                 case TYPE_T:
01120                                         if (1==sscanf(value,"%d",&(OIFList[i]->value.d)))
01121                                         {
01122                                                 time_t now=time(NULL);
01123                                                 // strict check on time
01124                                                 if ( (OIFList[i]->value.d<now+864000)&&(OIFList[i]->value.d>0) )
01125                                                 {
01126                                                         OIFList[i]->valid=1;
01127                                                 }
01128                                                 else
01129                                                 {
01130                                                         OIFList[i]->valid=0;
01131                                                 }
01132                                         }
01133                                         break;
01134                                 case TYPE_F:
01135                                 case TYPE_f:
01136                                 case TYPE_G:
01137                                         if (1==sscanf(value,"%f",&(OIFList[i]->value.f)))
01138                                         {
01139                                                 OIFList[i]->valid=1;
01140                                         }
01141                                         break;
01142                                 case TYPE_C:
01143                                 case TYPE_H:
01144                                         if (1==sscanf(value,"%x",&(OIFList[i]->value.d)))
01145                                         {
01146                                                 OIFList[i]->valid=1;
01147                                         }
01148                                         break;
01149                                 case TYPE_S:
01150                                         strcpy((char *)(OIFList[i]->value.s),value);
01151                                         OIFList[i]->valid=1;
01152                                         break;
01153                                 default:
01154                                         PrintError("unknown type %d\n",
01155                                                         OIFList[i]->type);
01156                         } // switch
01157                         if (OIFList[i]->valid==0)
01158                         {
01159                                 PrintDebug("could not fetch '%s'\n",OIFList[i]->name);
01160                         }
01161                         // stop searching here
01162                         break;
01163                 }
01164         }
01165         // if not found, return -1
01166         if (OIFList[i]==NULL)
01167         {
01168                 //PrintError("unknown parameter '%s'\n",name);
01169                 return(-1);
01170         }
01171         // if not valid, return -1 as well
01172         if (OIFList[i]->valid==0)
01173         {
01174                 return(-1);
01175         }
01176         return(0);
01177 }
01178 
01184 void PrintField(FILE *f, char *pre, struct OsirisInformationField *field, char *post)
01185 {
01186         int print=1;
01187         if (omniMode==0)
01188         {
01189                 if (field->valid==0)
01190                 {
01191                         print=0;
01192                 }
01193                 if ((field->verboseOnly==1)&&(verboseMode==0))
01194                 {
01195                         print=0;
01196                 }
01197         }
01198         if (print)
01199         {
01200                 fprintf(f,"%s",pre?pre:"");
01201                 if (field->valid==0)
01202                 {
01203                         fprintf(f,"?");
01204                 }
01205                 else
01206                 {
01207                         switch (field->type)
01208                         {
01209                                 case TYPE_C:
01210                                         fprintf(f,"%s",MaskToList(field->value.d));
01211                                         break;
01212                                 case TYPE_F:
01213                                         fprintf(f,"%.2f",field->value.f);
01214                                         break;
01215                                 case TYPE_f:
01216                                         fprintf(f,"%.0f",field->value.f);
01217                                         break;
01218                                 case TYPE_G:
01219                                         fprintf(f,"%f",field->value.f);
01220                                         break;
01221                                 case TYPE_D:
01222                                         fprintf(f,"%d",field->value.d);
01223                                         break;
01224                                 case TYPE_H:
01225                                         fprintf(f,"%#0x",field->value.d);
01226                                         break;
01227                                 case TYPE_S:
01228                                         fprintf(f,"%s",field->value.s);
01229                                         break;
01230                                 case TYPE_B:
01231                                         fprintf(f,"%s",field->value.d?"true":"false");
01232                                         break;
01233                                 case TYPE_O:
01234                                         fprintf(f,"%s",field->value.d?"on":"off");
01235                                         break;
01236                                 case TYPE_Y:
01237                                         fprintf(f,"%s",field->value.d?"yes":"no");
01238                                         break;
01239                                 case TYPE_T:
01240                                         if (field->value.d<=0)
01241                                         {
01242                                                 fputs("undefined",f);
01243                                         }
01244                                         else
01245                                         {
01246                                                 char tmps[128];
01247                                                 time_t t=field->value.d;
01248                                                 struct tm *tm;
01249                                                 tm=gmtime(&t);
01250                                                 strftime((char *)tmps,127,"%Y-%m-%d %T",tm);
01251                                                 fprintf(f,"%s",tmps);
01252                                         }
01253                                         break;
01254                                 default:
01255                                         fprintf(f,"...");
01256                         }
01257                 }
01258                 if (post) fprintf(f,"%s",post);
01259         }
01260 }
01261 
01263 void DumpOIF(void)
01264 {
01265         int i;
01266         // look for the file in the table
01267         for (i=0; OIFList[i]!=NULL; i++)
01268         {
01269                 if (OIFList[i]->valid==1)
01270                 {
01271                         printf("%s:",OIFList[i]->name);
01272                         switch (OIFList[i]->type)
01273                         {
01274                                 case TYPE_C:
01275                                         printf("%s\n",MaskToList(OIFList[i]->value.d));
01276                                         break;
01277                                 case TYPE_F:
01278                                         printf("%f\n",OIFList[i]->value.f);
01279                                         break;
01280                                 case TYPE_D:
01281                                         printf("%d\n",OIFList[i]->value.d);
01282                                         break;
01283                                 case TYPE_H:
01284                                         printf("%#0x\n",OIFList[i]->value.d);
01285                                         break;
01286                                 case TYPE_S:
01287                                         printf("%s\n",OIFList[i]->value.s);
01288                                         break;
01289                                 case TYPE_B:
01290                                         printf("%s\n",OIFList[i]->value.d?"true":"false");
01291                                         break;
01292                                 case TYPE_O:
01293                                         printf("%s\n",OIFList[i]->value.d?"on":"off");
01294                                         break;
01295                                 case TYPE_Y:
01296                                         printf("%s\n",OIFList[i]->value.d?"yes":"no");
01297                                         break;
01298                                 case TYPE_T:
01299                                         {
01300                                                 char tmps[128];
01301                                                 time_t t=OIFList[i]->value.d;
01302                                                 struct tm *tm;
01303                                                 tm=gmtime(&t);
01304