wmclockmon: update change-log
[dockapps.git] / wmspaceweather / wmSpaceWeather / wmSpaceWeather.c
blob3016d181ab9ad21de75db7cc74343f8b3a66f458
1 /*
3 * wmSpaceWeather-1.04 (C) 1998 Mike Henderson (mghenderson@lanl.gov)
5 * - Its a Space Weather Monitor
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program (see the file COPYING); if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA
25 * ToDo:
27 * - The whole NOAA space weather www site is pretty screwed up! I currently have
28 * to grab data from 2 separate files to get all that I need. But it seems that
29 * sometimes one of the files shows less than it should. This seems to be related to
30 * the way they update the 2 separate files... I will have to find some way of
31 * making that more robust.
41 * Changes:
43 * Version 1.04 - released Feb 18, 1999
44 * Added double click capability. Double clicking on mouse button 1 sends
45 * URL (defined via ne command line option -url) to netscape.
47 * Version 1.03 - released Feb 11, 1999
48 * Changed display a bit. When no data is
49 * available, it now shows nothing (before it would
50 * show false junk...). Modified Perl Script GetKp.
53 * Version 1.02 - released Feb 8, 1999
54 * bug fixes...
56 * Version 1.0b - released Dec 19, 1998
66 * Includes
68 #include <stdio.h>
69 #include <unistd.h>
70 #include <stdlib.h>
71 #include <string.h>
72 #include <time.h>
73 #include <X11/X.h>
74 #include <X11/xpm.h>
75 #include <libdockapp/wmgeneral.h>
76 #include "wmSpaceWeather_master.xpm"
77 #include "wmSpaceWeather_mask.xbm"
82 * Delay between refreshes (in microseconds)
84 #define DELAY 10000L
85 #define WMSPACEWEATHER_VERSION "1.04"
87 int GotFirstClick1, GotDoubleClick1;
88 int GotFirstClick2, GotDoubleClick2;
89 int GotFirstClick3, GotDoubleClick3;
90 int DblClkDelay;
91 char URL[1024];
92 int ForceUpdate2;
95 void ParseCMDLine(int argc, char *argv[]);
96 void pressEvent(XButtonEvent *xev);
108 * main
110 int main(int argc, char *argv[]) {
113 struct tm *Time;
114 XEvent event;
115 int i, n, s, k, m, dt1, dt2;
116 int Year, Month, Day, DayOfMonth, OldDayOfMonth;
117 int Hours, Mins, Secs, OldSecs, xoff, D[10], xsize;
118 long CurrentLocalTime;
119 int height, UpToDate, LEDOn;
120 double UT, TU, TU2, TU3, T0, gmst, hour24();
123 double jd(), CurrentJD, LatestAvailJD, tim, DeltaT;
124 long int TimeTag[8];
125 int Kp[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
126 double E1, E2, P1, P2, P3;
127 char Xray[10], digit[2];
128 FILE *fp;
141 * Parse any command line arguments.
143 ParseCMDLine(argc, argv);
147 openXwindow(argc, argv, wmSpaceWeather_master, wmSpaceWeather_mask_bits, wmSpaceWeather_mask_width, wmSpaceWeather_mask_height);
153 * Loop until we die
155 n = 32000;
156 s = 32000;
157 m = 32000;
158 dt1 = 32000;
159 dt2 = 32000;
160 LEDOn = 0;
161 DblClkDelay = 32000;
162 ForceUpdate2 = 1;
163 while(1) {
169 * Keep track of # of seconds
171 if (m > 100){
173 m = 0;
174 ++dt1;
175 ++dt2;
177 } else {
180 * Increment counter
182 ++m;
191 * Double Click Delays
192 * Keep track of click events. If Delay too long, set GotFirstClick's to False.
194 if (DblClkDelay > 15) {
196 DblClkDelay = 0;
197 GotFirstClick1 = 0; GotDoubleClick1 = 0;
198 GotFirstClick2 = 0; GotDoubleClick2 = 0;
199 GotFirstClick3 = 0; GotDoubleClick3 = 0;
201 } else {
203 ++DblClkDelay;
216 * Process any pending X events.
218 while(XPending(display)){
219 XNextEvent(display, &event);
220 switch(event.type){
221 case Expose:
222 RedrawWindow();
223 break;
224 case ButtonPress:
225 pressEvent(&event.xbutton);
226 break;
227 case ButtonRelease:
228 break;
238 * Redraw
240 RedrawWindow();
252 * Check the Kp file every (approx.) 2 seconds.
253 * Can significantly reduce this frequency later. But its
254 * easier to debug this way...
255 * Do this before trying to download again! The file may be there and it
256 * may be Up-To-Date!
258 if (dt2 > 2){
260 dt2 = 0;
263 * Compute Current Julian Date
265 CurrentLocalTime = time(CurrentTime);
266 Time = gmtime(&CurrentLocalTime);
267 Year = Time->tm_year+1900;
268 Month = Time->tm_mon+1;
269 Day = Time->tm_mday;
270 Hours = Time->tm_hour;
271 Mins = Time->tm_min;
272 Secs = Time->tm_sec;
273 UT = (double)Hours + (double)Mins/60.0 + (double)Secs/3600.0;
274 CurrentJD = jd(Year, Month, Day, UT);
279 * Read in Kp values
281 if ((fp = fopen("/tmp/LatestKp.txt", "r")) != NULL){
283 for (i=0; i<8; ++i){
284 fscanf(fp, "%ld %d", &TimeTag[i], &Kp[i]);
285 if (Kp[i] < 0) TimeTag[i] = 190001011;
287 fscanf(fp, "%lf", &P1);
288 fscanf(fp, "%lf", &P2);
289 fscanf(fp, "%lf", &P3);
290 fscanf(fp, "%lf", &E1);
291 fscanf(fp, "%lf", &E2);
292 fscanf(fp, "%10s", Xray);
293 fclose(fp);
295 } else {
297 for (i=0; i<8; ++i) {
298 Kp[i] = -1;
299 TimeTag[i] = 190001011;
308 * Compute Julian Date for latest available Kp
310 tim = TimeTag[7];
311 Year = tim/100000;
312 tim -= Year*100000;
313 Month = tim/1000;
314 tim -= Month*1000;
315 Day = tim/10;
316 tim -= Day*10;
317 UT = tim*3.0;
318 LatestAvailJD = jd(Year, Month, Day, UT);
320 DeltaT = (CurrentJD - LatestAvailJD)*24.0;
321 UpToDate = (DeltaT <= 3.0) ? 1 : 0;
323 if (!UpToDate){
326 * shift data back
328 k = (int)(DeltaT/3.0);
330 if ((k>=0)&&(k<=7)){
331 for (i=0; i<8-k; ++i) Kp[i] = Kp[i+k];
332 for (i=8-k; i<8; ++i) Kp[i] = -1;
346 * Update Kp Bars etc...
348 if (n > 200){
350 n = 0;
352 copyXPMArea(5, 67, 47, 20, 5, 39);
354 for (i=0; i<8; ++i){
355 if ((Kp[i] >= 0)&&(Kp[i] <= 9)){
356 height = 2*Kp[i] + 1;
357 copyXPMArea(53, 86-height+1, 5, height, 5+5*i+i, 58-height+1);
362 * Update Xray display...
364 if (Xray[0] != 'Z'){
365 switch(Xray[0]){
366 case 'B':
367 copyXPMArea(66, 17, 5, 7, 37, 25);
368 break;
369 case 'C':
370 copyXPMArea(72, 17, 5, 7, 37, 25);
371 break;
372 case 'M':
373 copyXPMArea(78, 17, 5, 7, 37, 25);
374 break;
375 case 'X':
376 copyXPMArea(84, 17, 5, 7, 37, 25);
377 break;
379 digit[0] = Xray[1]; digit[1] = '\0';
380 copyXPMArea(atoi(digit)*6+66, 25, 5, 7, 43, 25);
381 copyXPMArea(127, 30, 3, 3, 49, 30);
382 digit[0] = Xray[3]; digit[1] = '\0';
383 copyXPMArea(atoi(digit)*6+66, 25, 5, 7, 53, 25);
390 * Update E1 LED...
392 if ((E1 > 0)&&(E1 < 1e6))
393 copyXPMArea(66, 12, 4, 4, 25, 7);
394 else if ((E1 >= 1e6)&&(E1 < 1e7))
395 copyXPMArea(66, 7, 4, 4, 25, 7);
396 else if (E1 > 1e7)
397 copyXPMArea(66, 2, 4, 4, 25, 7);
401 * Update E2 LED...
403 if ((E2 > 0)&&(E2 < 1e3))
404 copyXPMArea(66, 12, 4, 4, 31, 7);
405 else if ((E2 >= 1e3)&&(E2 < 1e4))
406 copyXPMArea(66, 7, 4, 4, 31, 7);
407 else if (E2 > 1e4)
408 copyXPMArea(66, 2, 4, 4, 31, 7);
413 * Update P1 LED...
415 if ((P1 > 0)&&(P1 < 1e2))
416 copyXPMArea(66, 12, 4, 4, 22, 16);
417 else if ((P1 >= 1e2)&&(P1 < 1e3))
418 copyXPMArea(66, 7, 4, 4, 22, 16);
419 else if (P1 > 1e3)
420 copyXPMArea(66, 2, 4, 4, 22, 16);
424 * Update P2 LED...
426 if ((P2 > 0)&&(P2 < 0.5e0))
427 copyXPMArea(66, 12, 4, 4, 28, 16);
428 else if ((P2 >= 0.5e0)&&(P2 < 0.5e1))
429 copyXPMArea(66, 7, 4, 4, 28, 16);
430 else if (P2 > 0.5e1)
431 copyXPMArea(66, 2, 4, 4, 28, 16);
435 * Update P3 LED...
437 if ((P3 > 0)&&(P3 < 0.3e0))
438 copyXPMArea(66, 12, 4, 4, 34, 16);
439 else if ((P3 >= 0.3e0)&&(P3 < 0.3e1))
440 copyXPMArea(66, 7, 4, 4, 34, 16);
441 else if (P3 > 0.3e1)
442 copyXPMArea(66, 2, 4, 4, 34, 16);
452 } else {
455 * Increment counter
457 ++n;
466 * Update the blinking LED which indicates whether or not the
467 * display is up-to-date
469 if (s > 20){
471 s = 0;
473 if (LEDOn){
475 if (UpToDate)
476 copyXPMArea(65, 82, 4, 4, 54, 53);
477 else
478 copyXPMArea(65, 76, 4, 4, 54, 53);
480 LEDOn = 0;
482 } else {
484 if (UpToDate)
485 copyXPMArea(60, 82, 4, 4, 54, 53);
486 else
487 copyXPMArea(60, 76, 4, 4, 54, 53);
489 LEDOn = 1;
492 } else {
495 * Increment counter
497 ++s;
511 * Check every 5 min if the values are not up to date...
513 if (((!UpToDate)&&(dt1 > 300))||ForceUpdate2){
515 dt1 = 0;
518 * Execute Perl script to grab the Latest Kp values
520 system("GetKp &");
522 ForceUpdate2 = 0;
530 * Wait for next update
532 usleep(DELAY);
549 * ParseCMDLine()
551 void ParseCMDLine(int argc, char *argv[]) {
553 int i;
555 for (i = 1; i < argc; i++) {
557 if (!strcmp(argv[i], "-display")){
559 ++i;
561 } else if ((!strcmp(argv[i], "-url"))||(!strcmp(argv[i], "-u"))){
563 strcpy(URL, argv[++i]);
565 } else {
567 printf("\nwmSpaceWeather version: %s\n", WMSPACEWEATHER_VERSION);
568 printf("\nusage: wmSpaceWeather [-h] [-url <www URL>]\n\n");
569 printf("\t-url <URL>\tURL to send to Netscape with Button1 double click.\n\n");
570 printf("\t-h\t\tDisplay help screen.\n\n");
571 exit(1);
586 * Compute the Julian Day number for the given date.
587 * Julian Date is the number of days since noon of Jan 1 4713 B.C.
589 double jd(ny, nm, nd, UT)
590 int ny, nm, nd;
591 double UT;
593 double A, B, C, D, JD, MJD, day;
595 day = nd + UT/24.0;
598 if ((nm == 1) || (nm == 2)){
599 ny = ny - 1;
600 nm = nm + 12;
603 if (((double)ny+nm/12.0+day/365.25)>=(1582.0+10.0/12.0+15.0/365.25)){
604 A = ((int)(ny / 100.0));
605 B = 2.0 - A + (int)(A/4.0);
607 else{
608 B = 0.0;
610 if (ny < 0.0){
611 C = (int)((365.25*(double)ny) - 0.75);
613 else{
614 C = (int)(365.25*(double)ny);
617 D = (int)(30.6001*(double)(nm+1));
620 JD = B + C + D + day + 1720994.5;
621 return(JD);
629 * This routine handles button presses.
631 void pressEvent(XButtonEvent *xev){
633 char Command[512];
636 DblClkDelay = 0;
637 if ((xev->button == Button1) && (xev->type == ButtonPress)){
638 if (GotFirstClick1) GotDoubleClick1 = 1;
639 else GotFirstClick1 = 1;
640 } else if ((xev->button == Button2) && (xev->type == ButtonPress)){
641 if (GotFirstClick2) GotDoubleClick2 = 1;
642 else GotFirstClick2 = 1;
643 } else if ((xev->button == Button3) && (xev->type == ButtonPress)){
644 if (GotFirstClick3) GotDoubleClick3 = 1;
645 else GotFirstClick3 = 1;
649 * We got a double click on Mouse Button1 (i.e. the left one)
651 if (GotDoubleClick1) {
652 GotFirstClick1 = 0;
653 GotDoubleClick1 = 0;
654 sprintf(Command, "netscape -remote 'openURL(%s)' || netscape '%s' &", URL, URL);
655 system(Command);
660 * We got a double click on Mouse Button2 (i.e. the left one)
662 if (GotDoubleClick2) {
667 * We got a double click on Mouse Button3 (i.e. the left one)
669 if (GotDoubleClick3) {
670 GotFirstClick3 = 0;
671 GotDoubleClick3 = 0;
672 ForceUpdate2 = 1;
677 return;