updated removed
[home-automation.git] / thermometer.php
1 <?php
2 // Thermometer image script
3 // Ken True - webmaster@Saratoga-weather.org
4 // error_reporting(E_ALL); // uncomment to run testing
5 // Version 1.00 - 17-Sep-2007 - Initial release
6 // Version 1.01 - 18-Nov-2007 - added GD test, autoscale function, updated for sce=view on IIS systems
7 // Version 1.02 - 23-Nov-2007 - fixed Notice: errata on min/max calculations
8 // Version 1.03 - 28-Feb-2008 - added support for Carterlake/AJAX/PHP template integration
9 // Version 1.04 - 02-Feb-2009 - added support for 'dark' template (white text instead of black)
10 // Version 1.05 - 21-Oct-2009 - added support for Cumulus realtime.txt
11 //
12 // script available at http://saratoga-weather.org/scripts.php
13 //  
14 // you may copy/modify/use this script as you see fit,
15 // no warranty is expressed or implied.
16
17 // This script reads WD clientraw.txt , VWS wflash.txt/wflash2.txt, or Cumulus realtime.txt 
18 // gets the current, high, low temperature and draws a
19 // thermometer image (filled area + scale) on a transparent-background thermometer graphic 
20 // PNG.
21 //  usage on your page:
22 //
23 //  <img src="thermometer.php" height="170" width="54" alt="current temperature, daily low/high" />
24 //
25 // New with version 1.01 - $autoScale = true; enables autoranging on output scale.  The program will
26 // add majortick values to maximum or substract majortick values from minimum to always show the
27 // scale, current, minimum, maximum on the graphic.
28 //------------ settings ------------------
29 $wxSoftware         = 'WD';                           // 'WD' for Weather-Display, 'VWS' for Virtual Weather Station,
30                                                       // 'CU' for Cumulus
31 //
32 $UOM = 'F';                                           // set to 'C' for Celsius/Centigrade, 'F'=Fahrenheit
33 //
34 $autoScale = true;                                    // set to false to disable autoscale.
35 //
36 // you only have to set one of these correctly based on the $useWD selection
37 // $wxSoftware = 'WD' : set the $clientrawfile
38 // $wxSoftware = 'VWS': set the $wflashDir
39 // $wxSoftware = 'CU': set the $realtimefile
40 //
41 $clientrawfile = './clientraw.txt';                // relative file address for WD clientraw.txt
42 $wflashDir     = './wflash/Data/';                 // directory for the the VWS wflash.txt and wflash2.txt files
43 //                                                 // relative to directory location of this script (include
44 //                                                 // trailing '/' in the specification
45 $realtimefile  = './realtime.txt';                 // relative file location for Cumulus realtime.txt file
46 //
47 // settings for ranges -- adjust for your climate :-)
48 // Fahrenheit settings
49 $TmaxF = 105;     // maximum °F temperature on thermometer
50 $TminF = 10;      // minimum °F temperature on thermometer
51 $TincrF = 5;      // increment number of degrees °F for major/minor ticks on thermometer
52 $TMajTickF = 10;  // major tick with value when °F scale number divisible by this
53 // Centigrade settings
54 $TmaxC = 40;      // maximum °C temperature on thermometer
55 $TminC = -10;     // minimum °C temperature on thermometer
56 $TincrC = 2;      // increment number of degrees °C for major/minor ticks on thermometer
57 $TMajTickC = 10;  // major tick with value when °C scale number divisible by this
58 //
59 $invertColor = true; // set to true if thermometer display is over black background
60 $BlankGraphic  = './thermometer-blank.png'; // relative file address for thermometer blank image PNG
61 $BlankGraphicBlack = './thermometer-blank-black.png'; // for black background use
62 //------------ end settings --------------
63 // overrides from Settings.php if available
64 if(file_exists("Settings.php")) { include_once("Settings.php"); }
65 global $SITE;
66 if (isset($SITE['uomTemp']))    {
67   $UOM = preg_replace('|&deg;|is','',$SITE['uomTemp']);
68   if ($UOM <> 'F' and $UOM <> 'C') { $UOM = 'F'; }
69 }
70 if (isset($SITE['clientrawfile']) ) {$clientrawfile = $SITE['clientrawfile']; }
71 if (isset($SITE['wflashdir']) ) {$wflashDir = $SITE['wflashdir']; }
72 if (isset($SITE['realtimefile']) ) {$realtimefile = $SITE['realtimefile']; }
73 $CSSstyle = '';
74 # was there a style selected from the form input
75 if (isset($_COOKIE['CSSstyle'])) {
76        $_SESSION['CSSstyle'] = $_COOKIE['CSSstyle'];
77        $CSSstyle = $_COOKIE['CSSstyle'];
78   } else if (isset($_SESSION['CSSstyle']) and $_SESSION['CSSstyle'] <> '' ) {
79        $CSSstyle = $_SESSION['CSSstyle'];
80   }
81 if (preg_match('|black|i',$CSSstyle) ) {
82         $invertColor = true; 
83 }
84 // end of overrides from Settings.php
85
86 // -------------------begin code ------------------------------------------
87 if (isset($_REQUEST['sce']) && strtolower($_REQUEST['sce']) == 'view' ) {
88    //--self downloader --
89    $filenameReal = __FILE__;
90    $download_size = filesize($filenameReal);
91    header('Pragma: public');
92    header('Cache-Control: private');
93    header('Cache-Control: no-cache, must-revalidate');
94    header("Content-type: text/plain");
95    header("Accept-Ranges: bytes");
96    header("Content-Length: $download_size");
97    header('Connection: close');
98    
99    readfile($filenameReal);
100    exit;
101 }
102
103 if( ! function_exists("gd_info")){
104   die("Sorry.. this script requires the GD library in PHP to function.");
105 }
106
107
108 if (isset($_REQUEST['sw']) and strtolower($_REQUEST['sw']) == 'wd') { $wxSoftware = 'WD'; } // testing
109 if (isset($_REQUEST['sw']) and strtolower($_REQUEST['sw']) == 'vws') { $wxSoftware = 'VWS'; } // testing
110 if (isset($_REQUEST['sw']) and strtolower($_REQUEST['sw']) == 'cu') { $wxSoftware = 'CU'; } // testing
111
112 if (isset($_REQUEST['uom']) and strtolower($_REQUEST['uom']) == 'c') { $UOM = 'C'; }
113 if (isset($_REQUEST['uom']) and strtolower($_REQUEST['uom']) == 'f') { $UOM = 'F'; }
114 if (isset($_REQUEST['dark'])) {$invertColor = strtolower($_REQUEST['dark'])=='y'; }
115
116 if ($wxSoftware == 'WD') { // Get the Weather-Display clientraw.txt data file
117
118       //$dataraw = file_get_contents($clientrawfile);
119
120       // clean up any blank lines
121       
122       #$dataraw = trim($dataraw);
123       $dataraw = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/","\n",$dataraw);
124       $data = explode(" ", $dataraw);
125           
126           //$curtemp = CtoF('50',1);
127           //$mintemp = CtoF('20',1);
128           //$maxtemp = CtoF('80',1);
129           #$curtemp = '<!--outsideTemp-->';
130           $curtemp = $_GET['t'];
131           $mintemp = $_GET['mint'];
132           $maxtemp = $_GET['maxt'];
133           
134   } // end Weather Display data
135   
136 if ($wxSoftware == 'VWS') { // Get the VWS Weather Flash data files
137   
138       $filename = "${wflashDir}wflash.txt";
139       $file = file($filename);
140       $file = implode('',$file);
141       $data = explode(",",$file);;
142   
143           $curtemp = FtoC($data[9],1);
144           
145       $filename = "${wflashDir}wflash2.txt";
146       $file = file($filename);
147       $file = implode('',$file);
148       $data = explode(",",$file);;
149           
150           $mintemp = FtoC($data[92],1);
151           $maxtemp = FtoC($data[36],1);
152    }
153
154 if ($wxSoftware == 'CU') { // Get the Cumulus realtime.txt file
155   
156       $dataraw = file_get_contents($realtimefile);
157
158       // clean up any blank lines
159       $dataraw = trim($dataraw);
160       $dataraw = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/","\n",$dataraw);
161       $data = explode(" ", $dataraw);
162           $inUOM = $data[14];
163       if ($inUOM == 'F' and $UOM == 'C') {
164                 $curtemp = FtoC($data[2],1);
165                 $mintemp = FtoC($data[28],1);
166                 $maxtemp = FtoC($data[26],1);
167           } elseif ($inUOM == 'C' and $UOM == 'F') {
168                 $curtemp = CtoF($data[2],1);
169                 $mintemp = CtoF($data[28],1);
170                 $maxtemp = CtoF($data[26],1);
171           } else {
172                 $curtemp = $data[2];
173                 $mintemp = $data[28];
174                 $maxtemp = $data[26];
175                 $UOM = $inUOM;
176           }
177    }
178
179 if (isset($_REQUEST['current'])) { $curtemp = $_REQUEST['current']; } // for testing
180 if (isset($_REQUEST['min'])) { $mintemp = $_REQUEST['min']; } // for testing
181 if (isset($_REQUEST['max'])) { $maxtemp = $_REQUEST['max']; } // for testing
182
183
184 if ($UOM == 'F') { // use Fahrenheit settings
185     $Tmax = $TmaxF;   // maximum temperature on thermometer
186     $Tmin = $TminF;    // minimum temperature on thermometer
187     $Tincr = $TincrF;    // increment number of degrees for major/minor ticks on thermometer
188     $TMajTick = $TMajTickF;// major tick with value when scale number divisible by this
189   } else { // use Centigrade settings
190     $Tmax = $TmaxC;    // maximum temperature on thermometer
191     $Tmin = $TminC;   // minimum temperature on thermometer
192     $Tincr = $TincrC;    // increment number of degrees for major/minor ticks on thermometer
193     $TMajTick = $TMajTickC;// major tick with value when scale number divisible by this
194 }
195
196       if($autoScale) { autoscale($curtemp,$mintemp,$maxtemp); }
197           
198       genThermometer($curtemp, $mintemp,$maxtemp); // make graphic!
199           
200 return;
201           
202 // ----------- functions ----------------------------------------------------------
203 //
204 function genThermometer( $current,$min,$max ) {
205
206    global $UOM,$BlankGraphic,$BlankGraphicBlack,$wxSoftware,$invertColor;
207    global  $Tmax,$Tmin,$Tincr,$TMajTick;
208
209 // draw a filled thermometer with scale, min max on a blank thermometer image
210  $BGfile = $invertColor?$BlankGraphicBlack:$BlankGraphic;
211  $image = LoadPNG($BGfile);
212  
213  // settings relative to the thermometer image file defines the drawing area
214  // for the thermometer filling
215  // these settings are SPECIFICALLY for the thermometer-blank.png image background
216  
217  $minX = 20; // left
218  $maxX = 24; // right
219  $minY = 20; // top
220  $maxY = 140;// bottom
221  
222
223  $width = imagesx($image);
224  $height = imagesy($image);
225  $font = 1;
226
227  $bg    = imagecolorallocate($image,255,255,255 );
228  $tx    = imagecolorallocate($image,0,0,0);
229  $blue  = imagecolorallocate($image,0,0,255);
230  $red   = imagecolorallocate($image,255,0,0);
231  if ($invertColor) {
232    $tx    = imagecolorallocate($image,255,255,255);
233    $blue  = imagecolorallocate($image,0,192,255);
234    $red   = imagecolorallocate($image,255,32,32);
235  }
236   
237  $Trange = $Tmax - $Tmin; // total temperature range
238  
239  $Tpct = ($current-$Tmin)/($Trange); // percent for current temperature of range
240   
241  $Y = (1-$Tpct)*($maxY-$minY)+$minY; // upper location for fill
242   
243 // fill the thermometer with a red bar from bottom to $Y 
244   imagefilledrectangle( $image,
245                  $minX,
246                  $Y,
247                  $maxX,
248                  $maxY,
249                  $red );
250                                  
251 // Draw tick marks and scale values on right
252                          
253  for ($T=$Tmin;$T<=$Tmax;$T+=$Tincr) {
254    
255      $Tpct = ($T-$Tmin)/($Trange);
256      $Y = (1-$Tpct)*($maxY-$minY)+$minY;
257          
258          if ($T == 0 or ($T % $TMajTick) == 0) { // Major Tick
259          
260             imagefilledrectangle( $image,
261             $maxX+7 ,
262             $Y ,
263             $maxX+12,
264             $Y +1, $tx );
265
266         imagestring($image, $font,
267             $maxX + 14,
268             $Y - (ImageFontHeight($font)/2),
269             sprintf( "%2d", $T),$tx);
270          } else { // Minor tick
271         imagefilledrectangle( $image,
272             $maxX+7,
273             $Y ,
274             $maxX+9,
275             $Y +1, $tx );
276          }
277
278  
279  } // end do ticks legend
280  
281  if(isset($min)) { // put on minimum temp bar/value
282  
283 //     $Tpct = ($min-$Tmin)/($Trange);
284      $Tpct = ( ( (float)$min-$Tmin )/ $Trange );
285      $Y = (1-$Tpct)*($maxY-$minY)+$minY;
286          imagefilledrectangle( $image,
287             $minX - 18,
288             $Y ,
289             $minX - 5,
290            $Y +1, $blue );
291       $tstr = sprintf('%2d',round($min,0));
292           $tsize = strlen($tstr)*imagefontwidth($font+1);
293       imagestring($image, $font+1,
294             $minX - $tsize - 3 ,
295             $Y + 2 ,
296             $tstr,$blue);
297
298  }
299  
300  if(isset($max)) { // put on maximum temp bar/value
301  
302      $Tpct = ($max-$Tmin)/($Trange);
303      $Y = (1-$Tpct)*($maxY-$minY)+$minY;
304          imagefilledrectangle( $image,
305             $minX - 18,
306             $Y ,
307             $minX - 5,
308             $Y +1, $red );
309  
310       $tstr = sprintf('%2d',round($max,0));
311           $tsize = strlen($tstr)*imagefontwidth($font+1);
312
313       imagestring($image, $font+1,
314             $minX - $tsize - 3 ,
315             $Y - imagefontheight($font+1),
316             $tstr,$red);
317  }
318
319  // put legend on top with UOM
320  
321     $cnt = '°' . $UOM;
322     imagestring( $image, $font+2, ($width/2)-((strlen($cnt)/2)*ImageFontWidth($font+2)),
323        (10-(ImageFontHeight($font+2) / 2)),
324        $cnt, $tx);
325
326 // write current temperature on thermometer bulb        
327 //    $tstr = sprintf('%2d',round($current,0));
328 //      $tsize = strlen($cnt)*imagefontwidth($font);
329
330 //    imagestring($image, $font,
331 //            ($minX+$maxX)/2 - $tsize/2 -2 ,
332 //            $maxY+6,
333 //            $tstr,$bg);
334
335         
336 //imagestring( $image, $font, ($width/2)-((strlen($wxSoftware)/2)*imagefontwidth($font)),
337 //   $height-imagefontheight($font),
338 //      $wxSoftware,$tx);
339
340  // send the image
341  header("content-type: image/png");
342  imagepng($image);
343  imagedestroy($image);
344
345 } // end genThermometer
346
347 // load PNG image 
348 function LoadPNG ($imgname) { 
349    $im = @imagecreatefrompng ($imgname); /* Attempt to open */ 
350    if (!$im) { /* See if it failed */ 
351        $im  = imagecreate (150, 30); /* Create a blank image */ 
352        $bgc = imagecolorallocate ($im, 255, 255, 255); 
353        $tc  = imagecolorallocate ($im, 0, 0, 0); 
354        imagefilledrectangle ($im, 0, 0, 150, 30, $bgc); 
355        /* Output an errmsg */ 
356        imagestring ($im, 1, 5, 5, "Error loading $imgname", $tc); 
357    } 
358    return $im; 
359
360
361 // CtoF: converts degrees Celcius to degress Farenheight (from Anolecomputing.com)
362 function CtoF($value, $precision) {
363   global $UOM;
364   if ($UOM <> 'F') { 
365     return round($value,$precision); 
366   } else { 
367     return round($value = (($value * 9 / 5) + 32),$precision); 
368   }
369 } // end function C_to_F
370
371 // FtoC: converts degress Farenheight to degrees Celcius  (from Anolecomputing.com)
372 function FtoC($value, $precision) {
373   global $UOM;
374   if ($UOM == 'F') { 
375     return round($value,$precision); 
376   } else { 
377     return round(($value - 32) * (5/9),$precision); 
378   }
379 } // end function F to C
380
381 // autoscale function .. adjust scale to fit current conditions if need be.
382
383 function autoscale($curtemp,$mintemp,$maxtemp) {
384
385    global  $Tmax,$Tmin,$Tincr,$TMajTick;
386    
387    $highest = max($curtemp,$Tmax,$maxtemp);
388    $lowest = min($curtemp,$Tmin,$mintemp);
389    
390    
391    while ($Tmax < $highest) {
392      $Tmax += $TMajTick;
393    }
394   
395    while ($Tmin > $lowest) {
396      $Tmin = $Tmin - $TMajTick;
397    }
398    
399    return;
400
401
402 }
403 ?>