00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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;
00117 int32_t hostid;
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
00154
00155
00156
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
00170 memset(&myShi,0,sizeof(struct ShortInfos));
00171
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
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
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
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
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
00254
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
00274 stat(tmps,&st);
00275
00276
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
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 :
00313 sprintf(gpsd_GpsState.value.s,"sync");
00314 gpsd_OnOff.value.d=1;
00315 break;
00316 case 1 :
00317 sprintf(gpsd_GpsState.value.s,"waiting");
00318 gpsd_OnOff.value.d=1;
00319 break;
00320 case 0 :
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
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
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
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
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
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
00424 for (i=0; i<MAX_SAT; i++)
00425 {
00426 az[i]=el[i]=sn[i]=-1;
00427 }
00428
00429 im = gdImageCreate(XMAX, YMAX);
00430
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
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
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
00493 for (i=0; i<MAX_SAT; i++)
00494 {
00495
00496 if (az[i]>0)
00497 {
00498 float a;
00499 a=M_PI*(90.-(float)az[i])/180.;
00500
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
00510
00511 sprintf(line,"%02d",i);
00512 gdImageString(im, gdFontGetSmall(), x, y,
00513 (unsigned char *)line,
00514 (sn[i]>0)?green:grey);
00515
00516 }
00517
00518 }
00519
00520
00521 gdImageGif(im, fout);
00522 gdImageDestroy(im);
00523 }
00524
00525
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
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
01068 if (2!=sscanf(line,"%63s %63s",name,value))
01069 {
01070 return(-1);
01071 }
01072
01073 if (!strncasecmp(name,"comd_Node",strlen("comd_Node"))) return(0);
01074
01075
01076 for (i=0; OIFList[i]!=NULL; i++)
01077 {
01078
01079 if (strcasecmp(OIFList[i]->name,name)==0)
01080 {
01081
01082 switch (OIFList[i]->type)
01083 {
01084
01085 case TYPE_Y:
01086 case TYPE_O:
01087 case TYPE_B:
01088
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
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
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 }
01157 if (OIFList[i]->valid==0)
01158 {
01159 PrintDebug("could not fetch '%s'\n",OIFList[i]->name);
01160 }
01161
01162 break;
01163 }
01164 }
01165
01166 if (OIFList[i]==NULL)
01167 {
01168
01169 return(-1);
01170 }
01171
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
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