3 /* Copyright (C) 2002 Brad Jorsch <anomie@users.sourceforge.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "wmweather+.h"
38 /* Important variables */
40 static time_t mrf_time
=0;
41 static char *mrf_file
=NULL
;
42 static char *mrf_newfile
=NULL
;
43 static char *mrf_req
[2]={ NULL
, NULL
};
44 static struct forecast forecasts
[MRF_MAX
];
47 /********* init functions ************/
48 static int parse_mrf(char *file
);
50 static void reset_mrf(void){
53 for(i
=0; i
<MRF_MAX
; i
++) reset_forecast(&forecasts
[i
]);
59 struct subst_val subs
[]={
60 { 's', STRING
, &mrf_station
},
64 strncpy(bigbuf
, mrf_station
, BIGBUF_LEN
-14);
65 bigbuf
[BIGBUF_LEN
-14]='\0';
66 for(e
=bigbuf
; *e
!='\0'; e
++);
67 strcpy(e
, ".mrf.txt");
68 mrf_file
=get_pid_filename(bigbuf
);
69 strcpy(e
, ".new-mrf.txt");
70 mrf_newfile
=get_pid_filename(bigbuf
);
72 if((mrf_req
[0]=subst(mrf_uri
, subs
))==NULL
) die("init_mrf");
73 if(mrf_post
!=NULL
&& (mrf_req
[1]=subst(mrf_post
, subs
))==NULL
) die("init_mrf");
76 /* Remove stale file */
80 for(i
=0; i
<MRF_MAX
; i
++) add_forecast(&forecasts
[i
], "MRF", mrf_station
);
83 static void mrf_callback(char *filename
, void *v
){
86 if(stat(mrf_newfile
, &statbuf
)>=0){
87 if(S_ISREG(statbuf
.st_mode
) && statbuf
.st_size
!=0
88 && diff(mrf_newfile
, mrf_file
) && parse_mrf(mrf_newfile
)){
89 mrf_time
=find_next_time(mrf_newfile
, "MOS GUIDANCE", 1440);
90 rename(mrf_newfile
, mrf_file
);
93 if(!parse_mrf(mrf_file
)) reset_mrf();
98 void mrf_cleanup(void){
99 if(mrf_file
==NULL
) return;
104 void update_mrf(int force
){
107 if(mrf_file
==NULL
) return;
110 if(!force
&& mrf_time
>t
) return;
112 mrf_time
=find_next_time(mrf_file
, "MOS GUIDANCE", 15);
113 download_file(mrf_newfile
, mrf_req
[0], mrf_req
[1], 0, mrf_callback
, NULL
);
117 #define NEXT(s) free(s); \
118 len=getLine(&s, fp); \
119 if(strstr(s, "</PRE>")!=NULL) len=0;
121 #define DIE() return (free(s), fclose(fp), 0)
122 #define INT(c) (tmp[0]=*c, tmp[1]=*(c+1), tmp[2]=*(c+2), tmp[3]=0, atoi(tmp))
124 static int parse_mrf(char *file
){
131 char tmp
[4]={0, 0, 0, 0};
135 if((fp
=fopen(file
, "r"))==NULL
) return 0;
137 /* Look for something like an MRF coded forecast */
141 if((c
=strstr(s
, "MOS GUIDANCE"))!=NULL
) break;
144 if(c
==NULL
) return (fclose(fp
), 0);
146 if(c
==NULL
|| !isdigit(*(c
-1)) || !isdigit(*(c
+1))) DIE();
149 if(mon
<1 || mon
>12 || x
<1 || x
>31) DIE();
151 if(c
==NULL
|| !isdigit(*(c
-1)) || !isdigit(*(c
+1))) DIE();
156 if(strncmp(s
, "FHR", 3)) DIE();
161 if(!strncmp(s
, wdaynames
[i
], 3)) break;
165 if(x
>25 && day
<5) mon
++;
166 if(x
<5 && day
>25) mon
--;
167 for(m
=0; m
<MRF_MAX
; m
++){
170 fix_date(&mon
, &day
, &y
, &j
);
172 warn("Something wicked happened with the mrf_parse dates...");
175 forecasts
[m
].month
=mon
;
176 forecasts
[m
].day
=day
;
179 forecasts
[m
].hour
=-1;
186 if(!strncmp(s
, "X/N", 3)){
187 for(c
=s
+12, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
188 forecasts
[m
].high
=INT(c
);
189 if(c
+4<s
+len
) forecasts
[m
].low
=INT((c
+4));
193 if(!strncmp(s
, "TMP", 3)){
194 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
195 i
=INT(c
); j
=INT((c
+4));
196 if(i
!=999 && j
!=999) forecasts
[m
].temp
=(i
+j
)/2;
197 else if(i
!=999) forecasts
[m
].temp
=i
;
198 else if(j
!=999) forecasts
[m
].temp
=j
;
202 if(!strncmp(s
, "DPT", 3)){
203 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
204 i
=INT(c
); j
=INT((c
+4));
205 if(i
!=999 && j
!=999) forecasts
[m
].dewpt
=(i
+j
)/2;
206 else if(i
!=999) forecasts
[m
].dewpt
=i
;
207 else if(j
!=999) forecasts
[m
].dewpt
=j
;
211 if(!strncmp(s
, "WND", 3)){
212 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
213 i
=INT(c
); j
=INT((c
+4));
214 if(i
!=999 && j
!=999) forecasts
[m
].windspeed
=(i
+j
)/2;
215 else if(i
!=999) forecasts
[m
].windspeed
=i
;
216 else if(j
!=999) forecasts
[m
].windspeed
=j
;
220 if(!strncmp(s
, "T24", 3)){
221 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
223 if(i
!=999) forecasts
[m
].tstorm
=i
;
227 if(!strncmp(s
, "Q24", 3)){
228 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
230 if(i
!=9) forecasts
[m
].precipamt
=i
;
234 if(!strncmp(s
, "SNW", 3)){
235 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
237 if(i
!=9) forecasts
[m
].snowamt
=i
;
241 if(!strncmp(s
, "CLD", 3)){
242 for(c
=s
+13, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
243 if(*c
=='C') forecasts
[m
].sky
=0;
245 if(*(c
-4)=='C') forecasts
[m
].sky
=2;
246 else if(*(c
-4)=='O') forecasts
[m
].sky
=3;
247 else if(c
+4<s
+len
&& *(c
+4)=='C') forecasts
[m
].sky
=2;
248 else if(c
+4<s
+len
&& *(c
+4)=='O') forecasts
[m
].sky
=3;
249 else forecasts
[m
].sky
=3;
251 if(*c
=='O') forecasts
[m
].sky
=4;
255 if(!strncmp(s
, "PZP", 3)){
256 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
257 i
=INT(c
); j
=INT((c
+4));
258 if(i
!=999 && j
!=999) forecasts
[m
].frz
=(i
+j
)/2;
259 else if(i
!=999) forecasts
[m
].frz
=i
;
260 else if(j
!=999) forecasts
[m
].frz
=j
;
264 if(!strncmp(s
, "PSN", 3)){
265 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
266 i
=INT(c
); j
=INT((c
+4));
267 if(i
!=999 && j
!=999) forecasts
[m
].snow
=(i
+j
)/2;
268 else if(i
!=999) forecasts
[m
].snow
=i
;
269 else if(j
!=999) forecasts
[m
].snow
=j
;
273 if(!strncmp(s
, "PRS", 3)){
274 /* stick "rain & snow" prob into rain for later */
276 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
277 i
=INT(c
); j
=INT((c
+4));
278 if(i
!=999 && j
!=999) forecasts
[m
].rain
=(i
+j
)/2;
279 else if(i
!=999) forecasts
[m
].rain
=i
;
280 else if(j
!=999) forecasts
[m
].rain
=j
;
284 if(!strncmp(s
, "P24", 3)){
285 for(c
=s
+8, m
=0; c
<s
+len
&& m
<MRF_MAX
; c
+=8, m
++){
287 if(i
!=999) forecasts
[m
].pcp_total
=i
;
295 for(m
=0; m
<MRF_MAX
; m
++){
296 forecasts
[m
].rh
=rh_F(forecasts
[m
].temp
, forecasts
[m
].dewpt
);
297 forecasts
[m
].heatindex
=heatindex_F(forecasts
[m
].temp
, forecasts
[m
].rh
);
298 forecasts
[m
].windchill
=windchill_F(forecasts
[m
].temp
, forecasts
[m
].windspeed
);
299 /* real rain = 100 - frz - snow
300 * real snow = snow + "rain & snow"
302 i
=100-forecasts
[m
].frz
-forecasts
[m
].snow
;
303 forecasts
[m
].snow
+=forecasts
[m
].rain
;
305 forecasts
[m
].rain
=forecasts
[m
].rain
*forecasts
[m
].pcp_total
/100;
306 forecasts
[m
].snow
=forecasts
[m
].snow
*forecasts
[m
].pcp_total
/100;
307 forecasts
[m
].frz
=forecasts
[m
].frz
*forecasts
[m
].pcp_total
/100;
309 /* These aren't really useful here... */
310 forecasts
[m
].temp
=999;
311 forecasts
[m
].dewpt
=999;