681 lines
12 KiB
C
681 lines
12 KiB
C
/*
|
|
*
|
|
* wmSpaceWeather-1.04 (C) 1998 Mike Henderson (mghenderson@lanl.gov)
|
|
*
|
|
* - Its a Space Weather Monitor
|
|
*
|
|
*
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program (see the file COPYING); if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA
|
|
*
|
|
* ToDo:
|
|
*
|
|
* - The whole NOAA space weather www site is pretty screwed up! I currently have
|
|
* to grab data from 2 separate files to get all that I need. But it seems that
|
|
* sometimes one of the files shows less than it should. This seems to be related to
|
|
* the way they update the 2 separate files... I will have to find some way of
|
|
* making that more robust.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
* Changes:
|
|
*
|
|
* Version 1.04 - released Feb 18, 1999
|
|
* Added double click capability. Double clicking on mouse button 1 sends
|
|
* URL (defined via ne command line option -url) to netscape.
|
|
*
|
|
* Version 1.03 - released Feb 11, 1999
|
|
* Changed display a bit. When no data is
|
|
* available, it now shows nothing (before it would
|
|
* show false junk...). Modified Perl Script GetKp.
|
|
*
|
|
*
|
|
* Version 1.02 - released Feb 8, 1999
|
|
* bug fixes...
|
|
*
|
|
* Version 1.0b - released Dec 19, 1998
|
|
*
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Includes
|
|
*/
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <X11/X.h>
|
|
#include <X11/xpm.h>
|
|
#include "../wmgeneral/wmgeneral.h"
|
|
#include "wmSpaceWeather_master.xpm"
|
|
#include "wmSpaceWeather_mask.xbm"
|
|
|
|
|
|
|
|
/*
|
|
* Delay between refreshes (in microseconds)
|
|
*/
|
|
#define DELAY 10000L
|
|
#define WMSPACEWEATHER_VERSION "1.04"
|
|
|
|
int GotFirstClick1, GotDoubleClick1;
|
|
int GotFirstClick2, GotDoubleClick2;
|
|
int GotFirstClick3, GotDoubleClick3;
|
|
int DblClkDelay;
|
|
char URL[1024];
|
|
int ForceUpdate2;
|
|
|
|
|
|
void ParseCMDLine(int argc, char *argv[]);
|
|
void pressEvent(XButtonEvent *xev);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* main
|
|
*/
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
|
struct tm *Time;
|
|
XEvent event;
|
|
int i, n, s, k, m, dt1, dt2;
|
|
int Year, Month, Day, DayOfMonth, OldDayOfMonth;
|
|
int Hours, Mins, Secs, OldSecs, xoff, D[10], xsize;
|
|
long CurrentLocalTime;
|
|
int height, UpToDate, LEDOn;
|
|
double UT, TU, TU2, TU3, T0, gmst, hour24();
|
|
|
|
|
|
double jd(), CurrentJD, LatestAvailJD, tim, DeltaT;
|
|
long int TimeTag[8];
|
|
int Kp[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
|
|
double E1, E2, P1, P2, P3;
|
|
char Xray[10], digit[2];
|
|
FILE *fp;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Parse any command line arguments.
|
|
*/
|
|
ParseCMDLine(argc, argv);
|
|
|
|
|
|
|
|
openXwindow(argc, argv, wmSpaceWeather_master, wmSpaceWeather_mask_bits, wmSpaceWeather_mask_width, wmSpaceWeather_mask_height);
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Loop until we die
|
|
*/
|
|
n = 32000;
|
|
s = 32000;
|
|
m = 32000;
|
|
dt1 = 32000;
|
|
dt2 = 32000;
|
|
LEDOn = 0;
|
|
DblClkDelay = 32000;
|
|
ForceUpdate2 = 1;
|
|
while(1) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Keep track of # of seconds
|
|
*/
|
|
if (m > 100){
|
|
|
|
m = 0;
|
|
++dt1;
|
|
++dt2;
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Increment counter
|
|
*/
|
|
++m;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Double Click Delays
|
|
* Keep track of click events. If Delay too long, set GotFirstClick's to False.
|
|
*/
|
|
if (DblClkDelay > 15) {
|
|
|
|
DblClkDelay = 0;
|
|
GotFirstClick1 = 0; GotDoubleClick1 = 0;
|
|
GotFirstClick2 = 0; GotDoubleClick2 = 0;
|
|
GotFirstClick3 = 0; GotDoubleClick3 = 0;
|
|
|
|
} else {
|
|
|
|
++DblClkDelay;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Process any pending X events.
|
|
*/
|
|
while(XPending(display)){
|
|
XNextEvent(display, &event);
|
|
switch(event.type){
|
|
case Expose:
|
|
RedrawWindow();
|
|
break;
|
|
case ButtonPress:
|
|
pressEvent(&event.xbutton);
|
|
break;
|
|
case ButtonRelease:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Redraw
|
|
*/
|
|
RedrawWindow();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Check the Kp file every (approx.) 2 seconds.
|
|
* Can significantly reduce this frequency later. But its
|
|
* easier to debug this way...
|
|
* Do this before trying to download again! The file may be there and it
|
|
* may be Up-To-Date!
|
|
*/
|
|
if (dt2 > 2){
|
|
|
|
dt2 = 0;
|
|
|
|
/*
|
|
* Compute Current Julian Date
|
|
*/
|
|
CurrentLocalTime = time(CurrentTime);
|
|
Time = gmtime(&CurrentLocalTime);
|
|
Year = Time->tm_year+1900;
|
|
Month = Time->tm_mon+1;
|
|
Day = Time->tm_mday;
|
|
Hours = Time->tm_hour;
|
|
Mins = Time->tm_min;
|
|
Secs = Time->tm_sec;
|
|
UT = (double)Hours + (double)Mins/60.0 + (double)Secs/3600.0;
|
|
CurrentJD = jd(Year, Month, Day, UT);
|
|
|
|
|
|
|
|
/*
|
|
* Read in Kp values
|
|
*/
|
|
if ((fp = fopen("/tmp/LatestKp.txt", "r")) != NULL){
|
|
|
|
for (i=0; i<8; ++i){
|
|
fscanf(fp, "%ld %d", &TimeTag[i], &Kp[i]);
|
|
if (Kp[i] < 0) TimeTag[i] = 190001011;
|
|
}
|
|
fscanf(fp, "%lf", &P1);
|
|
fscanf(fp, "%lf", &P2);
|
|
fscanf(fp, "%lf", &P3);
|
|
fscanf(fp, "%lf", &E1);
|
|
fscanf(fp, "%lf", &E2);
|
|
fscanf(fp, "%10s", Xray);
|
|
fclose(fp);
|
|
|
|
} else {
|
|
|
|
for (i=0; i<8; ++i) {
|
|
Kp[i] = -1;
|
|
TimeTag[i] = 190001011;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Compute Julian Date for latest available Kp
|
|
*/
|
|
tim = TimeTag[7];
|
|
Year = tim/100000;
|
|
tim -= Year*100000;
|
|
Month = tim/1000;
|
|
tim -= Month*1000;
|
|
Day = tim/10;
|
|
tim -= Day*10;
|
|
UT = tim*3.0;
|
|
LatestAvailJD = jd(Year, Month, Day, UT);
|
|
|
|
DeltaT = (CurrentJD - LatestAvailJD)*24.0;
|
|
UpToDate = (DeltaT <= 3.0) ? 1 : 0;
|
|
|
|
if (!UpToDate){
|
|
|
|
/*
|
|
* shift data back
|
|
*/
|
|
k = (int)(DeltaT/3.0);
|
|
|
|
if ((k>=0)&&(k<=7)){
|
|
for (i=0; i<8-k; ++i) Kp[i] = Kp[i+k];
|
|
for (i=8-k; i<8; ++i) Kp[i] = -1;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Update Kp Bars etc...
|
|
*/
|
|
if (n > 200){
|
|
|
|
n = 0;
|
|
|
|
copyXPMArea(5, 67, 47, 20, 5, 39);
|
|
|
|
for (i=0; i<8; ++i){
|
|
if ((Kp[i] >= 0)&&(Kp[i] <= 9)){
|
|
height = 2*Kp[i] + 1;
|
|
copyXPMArea(53, 86-height+1, 5, height, 5+5*i+i, 58-height+1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Update Xray display...
|
|
*/
|
|
if (Xray[0] != 'Z'){
|
|
switch(Xray[0]){
|
|
case 'B':
|
|
copyXPMArea(66, 17, 5, 7, 37, 25);
|
|
break;
|
|
case 'C':
|
|
copyXPMArea(72, 17, 5, 7, 37, 25);
|
|
break;
|
|
case 'M':
|
|
copyXPMArea(78, 17, 5, 7, 37, 25);
|
|
break;
|
|
case 'X':
|
|
copyXPMArea(84, 17, 5, 7, 37, 25);
|
|
break;
|
|
}
|
|
digit[0] = Xray[1]; digit[1] = '\0';
|
|
copyXPMArea(atoi(digit)*6+66, 25, 5, 7, 43, 25);
|
|
copyXPMArea(127, 30, 3, 3, 49, 30);
|
|
digit[0] = Xray[3]; digit[1] = '\0';
|
|
copyXPMArea(atoi(digit)*6+66, 25, 5, 7, 53, 25);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Update E1 LED...
|
|
*/
|
|
if ((E1 > 0)&&(E1 < 1e6))
|
|
copyXPMArea(66, 12, 4, 4, 25, 7);
|
|
else if ((E1 >= 1e6)&&(E1 < 1e7))
|
|
copyXPMArea(66, 7, 4, 4, 25, 7);
|
|
else if (E1 > 1e7)
|
|
copyXPMArea(66, 2, 4, 4, 25, 7);
|
|
|
|
|
|
/*
|
|
* Update E2 LED...
|
|
*/
|
|
if ((E2 > 0)&&(E2 < 1e3))
|
|
copyXPMArea(66, 12, 4, 4, 31, 7);
|
|
else if ((E2 >= 1e3)&&(E2 < 1e4))
|
|
copyXPMArea(66, 7, 4, 4, 31, 7);
|
|
else if (E2 > 1e4)
|
|
copyXPMArea(66, 2, 4, 4, 31, 7);
|
|
|
|
|
|
|
|
/*
|
|
* Update P1 LED...
|
|
*/
|
|
if ((P1 > 0)&&(P1 < 1e2))
|
|
copyXPMArea(66, 12, 4, 4, 22, 16);
|
|
else if ((P1 >= 1e2)&&(P1 < 1e3))
|
|
copyXPMArea(66, 7, 4, 4, 22, 16);
|
|
else if (P1 > 1e3)
|
|
copyXPMArea(66, 2, 4, 4, 22, 16);
|
|
|
|
|
|
/*
|
|
* Update P2 LED...
|
|
*/
|
|
if ((P2 > 0)&&(P2 < 0.5e0))
|
|
copyXPMArea(66, 12, 4, 4, 28, 16);
|
|
else if ((P2 >= 0.5e0)&&(P2 < 0.5e1))
|
|
copyXPMArea(66, 7, 4, 4, 28, 16);
|
|
else if (P2 > 0.5e1)
|
|
copyXPMArea(66, 2, 4, 4, 28, 16);
|
|
|
|
|
|
/*
|
|
* Update P3 LED...
|
|
*/
|
|
if ((P3 > 0)&&(P3 < 0.3e0))
|
|
copyXPMArea(66, 12, 4, 4, 34, 16);
|
|
else if ((P3 >= 0.3e0)&&(P3 < 0.3e1))
|
|
copyXPMArea(66, 7, 4, 4, 34, 16);
|
|
else if (P3 > 0.3e1)
|
|
copyXPMArea(66, 2, 4, 4, 34, 16);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Increment counter
|
|
*/
|
|
++n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Update the blinking LED which indicates whether or not the
|
|
* display is up-to-date
|
|
*/
|
|
if (s > 20){
|
|
|
|
s = 0;
|
|
|
|
if (LEDOn){
|
|
|
|
if (UpToDate)
|
|
copyXPMArea(65, 82, 4, 4, 54, 53);
|
|
else
|
|
copyXPMArea(65, 76, 4, 4, 54, 53);
|
|
|
|
LEDOn = 0;
|
|
|
|
} else {
|
|
|
|
if (UpToDate)
|
|
copyXPMArea(60, 82, 4, 4, 54, 53);
|
|
else
|
|
copyXPMArea(60, 76, 4, 4, 54, 53);
|
|
|
|
LEDOn = 1;
|
|
|
|
}
|
|
} else {
|
|
|
|
/*
|
|
* Increment counter
|
|
*/
|
|
++s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Check every 5 min if the values are not up to date...
|
|
*/
|
|
if (((!UpToDate)&&(dt1 > 300))||ForceUpdate2){
|
|
|
|
dt1 = 0;
|
|
|
|
/*
|
|
* Execute Perl script to grab the Latest Kp values
|
|
*/
|
|
system("GetKp &");
|
|
|
|
ForceUpdate2 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Wait for next update
|
|
*/
|
|
usleep(DELAY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* ParseCMDLine()
|
|
*/
|
|
void ParseCMDLine(int argc, char *argv[]) {
|
|
|
|
int i;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
if (!strcmp(argv[i], "-display")){
|
|
|
|
++i;
|
|
|
|
} else if ((!strcmp(argv[i], "-url"))||(!strcmp(argv[i], "-u"))){
|
|
|
|
strcpy(URL, argv[++i]);
|
|
|
|
} else {
|
|
|
|
printf("\nwmSpaceWeather version: %s\n", WMSPACEWEATHER_VERSION);
|
|
printf("\nusage: wmSpaceWeather [-h] [-url <www URL>]\n\n");
|
|
printf("\t-url <URL>\tURL to send to Netscape with Button1 double click.\n\n");
|
|
printf("\t-h\t\tDisplay help screen.\n\n");
|
|
exit(1);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Compute the Julian Day number for the given date.
|
|
* Julian Date is the number of days since noon of Jan 1 4713 B.C.
|
|
*/
|
|
double jd(ny, nm, nd, UT)
|
|
int ny, nm, nd;
|
|
double UT;
|
|
{
|
|
double A, B, C, D, JD, MJD, day;
|
|
|
|
day = nd + UT/24.0;
|
|
|
|
|
|
if ((nm == 1) || (nm == 2)){
|
|
ny = ny - 1;
|
|
nm = nm + 12;
|
|
}
|
|
|
|
if (((double)ny+nm/12.0+day/365.25)>=(1582.0+10.0/12.0+15.0/365.25)){
|
|
A = ((int)(ny / 100.0));
|
|
B = 2.0 - A + (int)(A/4.0);
|
|
}
|
|
else{
|
|
B = 0.0;
|
|
}
|
|
if (ny < 0.0){
|
|
C = (int)((365.25*(double)ny) - 0.75);
|
|
}
|
|
else{
|
|
C = (int)(365.25*(double)ny);
|
|
}
|
|
|
|
D = (int)(30.6001*(double)(nm+1));
|
|
|
|
|
|
JD = B + C + D + day + 1720994.5;
|
|
return(JD);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* This routine handles button presses.
|
|
*/
|
|
void pressEvent(XButtonEvent *xev){
|
|
|
|
char Command[512];
|
|
|
|
|
|
DblClkDelay = 0;
|
|
if ((xev->button == Button1) && (xev->type == ButtonPress)){
|
|
if (GotFirstClick1) GotDoubleClick1 = 1;
|
|
else GotFirstClick1 = 1;
|
|
} else if ((xev->button == Button2) && (xev->type == ButtonPress)){
|
|
if (GotFirstClick2) GotDoubleClick2 = 1;
|
|
else GotFirstClick2 = 1;
|
|
} else if ((xev->button == Button3) && (xev->type == ButtonPress)){
|
|
if (GotFirstClick3) GotDoubleClick3 = 1;
|
|
else GotFirstClick3 = 1;
|
|
}
|
|
|
|
/*
|
|
* We got a double click on Mouse Button1 (i.e. the left one)
|
|
*/
|
|
if (GotDoubleClick1) {
|
|
GotFirstClick1 = 0;
|
|
GotDoubleClick1 = 0;
|
|
sprintf(Command, "netscape -remote 'openURL(%s)' || netscape '%s' &", URL, URL);
|
|
system(Command);
|
|
}
|
|
|
|
|
|
/*
|
|
* We got a double click on Mouse Button2 (i.e. the left one)
|
|
*/
|
|
if (GotDoubleClick2) {
|
|
}
|
|
|
|
|
|
/*
|
|
* We got a double click on Mouse Button3 (i.e. the left one)
|
|
*/
|
|
if (GotDoubleClick3) {
|
|
GotFirstClick3 = 0;
|
|
GotDoubleClick3 = 0;
|
|
ForceUpdate2 = 1;
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|