Forecasts
Flash Welcome
Wx Video
Current Conditions
Radar Views
Satellite
Hazardous Wx Outlook
Watches & Warnings
SPC Outlook
Blogs
Equipment
Webcam
Road Conditions
About
Music
Site Map
e-mail me



NOAA Forecast

(.*)
 

CRH.noaa.gov redirects (no point forecasts) // Version 2.02 - 02-Mar-2007 - added auto-failover to CRH and better include in page. // Version 2.03 - 29-Apr-2007 - modified for /images/wtf -> /forecast/images change // Version 2.04 - 05-Jun-2007 - improvement to auto-failover // Version 2.05 - 29-Jun-2007 - additional check for alternative no-icon forecast, then failover. // Version 2.06 - 24-Nov-2007 - rewrite for zone forecast, intrepret icons from text-only forecast // Version 2.07 - 24-Nov-2007 - support new zone forecast with different temp formats // Version 2.08 - 25-Nov-2007 - fix zone forecast icons, new temp formats supported // Version 2.09 - 26-Nov-2007 - add support for new temperature phrases and below zero temps // Version 2.10 - 17-Dec-2007 - added safety features from Mike Challis http://www.carmosaic.com/weather/ // $Version = 'advforecast2.php - V2.10 - 17-Dec-2007'; // //import NOAA Forecast info //data ends up in four different arrays: //$forecasticons[x] x = 0 thru 9 This is the icon and text around it //$forecasttemp[x] x= 0 thru 9 This is forecast temperature with styling //$forecasttitles[x] x = 0 thru 12 This is the title word for the text forecast time period //$forecasttext[x] x = 0 thru 12 This is the detail text for the text forecast time period // //$forecastupdate This is the time of last update //$forecastcity This is the city name for the forecast //$forecastoffice This is the NWS Office providing the forecast // //Also, in order for this to work correctly, you need the NOAA icons (or make your own... //there are over 200!). These need to be placed in the path where the original NOAA icons //are located. In my case, they are at: \forecast\images\ //properly (so make a folder in your web HTML root called "forecast", then make a folder in it //called "images", and place the icons in this folder) // //http://members.cox.net/carterlakeweather/forecasticons.zip (380K) // //URL below --MUST BE-- the Printable Point Forecast from the NOAA website // //Not every area of the US has a printable point forecast // //This script will ONLY WORK with a printable point forecast! // //To find yours in your area: // //Go to www.weather.gov //Put your city, state in the search box and press Search //Scroll down to the "Additional Forecasts & Info" on the page displayed //Click on Printable Forecast // copy the URL from your browser into the $fileName variable below. // Also put your NOAA Warning Zone (like ssZnnn) in caps in the $NOAAZone variable below. // // also set your NOAA warning zone here to use for automatic backup in case // the point printable forecast is not available. // // ----------------------SETTINGS--------------------------------------------- // $NOAAZone = 'IAZ055'; // change this line to your NOAA warning zone. // set $fileName to the URL for the point-printable forecast for your area $fileName = "http://forecast.weather.gov/MapClick.php?CityName=Missouri+Valley&state=IA&site=OAX&textField1=41.5589&textField2=-95.8951&e=0&TextType=2"; // // ----------------------END OF SETTINGS-------------------------------------- // Get the forecast.txt file or a new one from NOAA // You have to have a forecast.txt in place for this script to work // You can see ours at http://www.carterlake.org/forecast.txt // This is version 1.2 with Ken's modifications from Saratoga Weather // http://saratoga-weather.org/ // You can now force the cache to update by adding ?force=1 to the end of the URL if ( empty($_REQUEST['force']) ) $_REQUEST['force']="0"; $Force = $_REQUEST['force']; $forceBackup = false; if ($Force > 1) {$forceBackup = true; } $cacheName = "forecast.txt"; // dont change the next line.... $backupfileName = "http://forecast.weather.gov/MapClick.php?zoneid=$NOAAZone"; $Status = "\n\n\n"; if (isset($_REQUEST['sce']) && strtolower($_REQUEST['sce']) == 'view' ) { //--self downloader -- $filenameReal = __FILE__; $download_size = filesize($filenameReal); header('Pragma: public'); header('Cache-Control: private'); header('Cache-Control: no-cache, must-revalidate'); header("Content-type: text/plain"); header("Accept-Ranges: bytes"); header("Content-Length: $download_size"); header('Connection: close'); readfile($filenameReal); exit; } $fcstPeriods = array( // for filling in the ' Through ' zone forecasts. 'Monday','Monday Night', 'Tuesday','Tuesday Night', 'Wednesday','Wednesday Night', 'Thursday','Thursday Night', 'Friday','Friday Night', 'Saturday','Saturday Night', 'Sunday','Sunday Night', 'Monday','Monday Night', 'Tuesday','Tuesday Night', 'Wednesday','Wednesday Night', 'Thursday','Thursday Night', 'Friday','Friday Night', 'Saturday','Saturday Night', 'Sunday','Sunday Night' ); $usingFile = ""; if ($Force==1) { $html = fetchUrlWithoutHanging($fileName,$cacheName); if (preg_match('/Temporary|Location:|defaulting to/Uis',$html)) { $usingFile = "(Zone forecast)"; $html = fetchUrlWithoutHanging($backupfileName,$cacheName); } $fp = fopen($cacheName, "w"); if ($fp) { $write = fputs($fp, $html); fclose($fp); } else { $Status .= "\n"; } } if ($Force==2) { $html = fetchUrlWithoutHanging($backupfileName,$cacheName); $fp = fopen($cacheName, "w"); if ($fp) { $write = fputs($fp, $html); fclose($fp); } else { $Status .= "\n"; } $usingFile = "(Zone forecast)"; } // The number 1800 below is the number of seconds the cache will be used instead of pulling a new file // 1800 = 60s x 30m so it retreives every 30 minutes. if (filemtime($cacheName) + 1800 > time()) { $Status .= "\n"; $html = implode('', file($cacheName)); if (preg_match('/Temporary|Location:|defaulting to/is',$html)) { $usingFile = "(Zone forecast)"; $html = fetchUrlWithoutHanging($backupfileName,$cacheName); } } else { $html = fetchUrlWithoutHanging($fileName,$cacheName); if (preg_match('/Temporary|Location:|defaulting to/Uis',$html)) { $usingFile = "(Zone forecast)"; $html = fetchUrlWithoutHanging($backupfileName,$cacheName); } $fp = fopen($cacheName, "w"); if ($fp) { $write = fputs($fp, $html); fclose($fp); } else { $Status .= "\n"; } } if (isset($_REQUEST['test'])) { $tfile = "./forecast-" . trim($_REQUEST['test']) . '.txt'; if(file_exists($tfile)) { $Status .= "\n"; $html = implode('',file($tfile)); } else { $Status .= "\n"; } } $isZone = preg_match('|Zone Forecast: |i',$html); // here with Zone forecast sans icons if ($isZone) { // using the zone forecast $usingFile = "(Zone forecast)"; $Conditions = array(); // prepare for parsing the icon based on the text forecast load_cond_data(); // initialize the conditions to look for preg_match( '|(.*)

|Uis', $html, $betweenspan); // $Status .= "\n"; $forecastop = $betweenspan[1]; // slice off the text forecast from the Zone forecast preg_match_all("|(.*)\.\.\.(.*)

|Uis", $forecastop, $headers); $forecaststuff = $headers[1]; // $Status .= "\n"; // Breakup multi-day forecasts if needed $i = 0; foreach ($headers[1] as $j => $period) { if (preg_match('/^(.*) (Through|And) (.*)/i',$period,$mtemp)) { // got period1 thru period2 list($fcstLow,$fcstHigh) = explode("\t",split_fcst($headers[2][$j])); $startPeriod = $mtemp[1]; $periodType = $mtemp[2]; $endPeriod = $mtemp[3]; $startIndex = 0; $endIndex = 0; $Status .= "\n"; for ($k=0;$k\n"; $i++; } continue; } $forecasttitles[$i] = $period; $forecasttext[$i] = $headers[2][$j]; $Status .= "\n"; $i++; } // end of multi-day forecast split for ($i=0;$i<=min(8,count($headers[1])-1);$i++) { // intrepet the text for icons, summary, temp, PoP list($forecasticons[$i],$forecasttemp[$i],$forecastpop[$i]) = explode("\t",make_icon($forecasttitles[$i],$forecasttext[$i]) ); } } else { // original format point printable forecast preg_match('|
(.*)<\/td>/Uis", $forecastop, $headers); $forecasticons = $headers[1]; } // saratoga-weather.org mod: fix up html for XHTML 1.0-Strict // $Status .= "\n"; for ($i=0;$i
\s+$|is', "",$forecasticons[$i]); // $forecasticons[$i] = preg_replace('|temperatures|is','temps',$forecasticons[$i]); // $forecasticons[$i] = preg_replace('|Falling|is',' Falling',$forecasticons[$i]); $forecasticons[$i] = preg_replace('|\'|is','"',$forecasticons[$i]); // change all ' to " $forecasticons[$i] = preg_replace('|\\\\" >
|is','" />
',$forecasticons[$i]); $forecasticons[$i] = preg_replace('|(.*)|Uis', "$2",$forecasticons[$i]); preg_match_all('|
([^<]+)(.*)|is',$forecasticons[$i],$matches); // $Status .= "\n"; if(isset($matches[2][0]) and preg_match('||i',$matches[2][0])) { $t = $matches[2][0]; $t = preg_replace('|([^|i', "\"\\3\"",$t); $matches[2][0] = $t; } if (! $isZone) { $forecasttemp[$i] = $matches[1][0] . $matches[2][0]; // just the temp line # mchallis added security feature $forecasttemp[$i] = strip_tags($forecasttemp[$i], '

'); } // remove the temp from the forecasticons if(isset($matches[0][0])) { $forecasticons[$i] = preg_replace('|'.$matches[0][0].'|is','',$forecasticons[$i]); } // fix up the
to be
for XHTML compatibility $forecasticons[$i] = preg_replace('|
|Uis','
',$forecasticons[$i]); # mchallis added security feature $forecasticons[$i] = strip_tags($forecasticons[$i], '

'); // $forecasttemp[$i] = preg_replace('|
|Uis','
',$forecasttemp[$i]); // $forecasttemp[$i] = trim($forecasttemp[$i]); } // $Status .= "\n"; // end saratoga-weather.org XHTML 1.0-Strict mod if ($isZone) { // special handling for ERH->CRH redirection // Grab the Last Update date and time. preg_match('|Last Update:(.*)
|', $html, $betweenspan); $forecastupdated = $betweenspan[1]; # mchallis added security feature $forecastupdated = strip_tags($forecastupdated, '
'); // saratoga-weather.org mod: // Grab the NWS Forecast for (city name) preg_match('|class="white1">\s*(.*)
'); // Grab the Issued by office preg_match('|
]+>(.*)
Zone Forecast:|is',$html,$betweenspan); $forecastoffice = trim($betweenspan[1]); $forecastoffice = preg_replace('|
|s','',$forecastoffice); } else { // begin regular handling // Now get just the bottom of the NWS page for editing preg_match('|
(.*)
|s', $html, $betweenspan); $forecast = $betweenspan[1]; # mchallis added security feature $forecast = strip_tags($forecast, '
'); // Chop up each title text and place in array preg_match_all('|(.*): |Ui', $forecast, $headers); $forecasttitles = $headers[1]; // Chop up each forecast text and place in array preg_match_all('|
(.*)
|Ui', $forecast, $headers); $forecasttext = $headers[1]; # BOF mchallis added security feature for ($i=0;$i
'); $forecasttext[$i] = strip_tags($forecasttext[$i], '
'); } # EOF mchallis added security feature // Grab the Last Update date and time. preg_match('|Last Update: (.*)|', $html, $betweenspan); $forecastupdated = $betweenspan[1]; $forecastupdated = preg_replace('|<[^>]+>|Uis','',$forecastupdated); // remove html markup // saratoga-weather.org mod: // Grab the NWS Forecast for (city name) preg_match('|NWS Forecast for: (.*)|',$html,$betweenspan); $forecastcity = $betweenspan[1]; # mchallis added security feature $forecastcity = strip_tags($forecastcity, '
'); // Grab the Issued by office preg_match('|Issued by: (.*)
|',$html,$betweenspan); $forecastoffice = $betweenspan[1]; # mchallis added security feature $forecastoffice = strip_tags($forecastoffice, '
'); } // end regular handling $IncludeMode = false; $PrintMode = true; if (isset($doPrintNWS) && ! $doPrintNWS ) { return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'noprint' ) { return; } if (isset($_REQUEST['inc']) && strtolower($_REQUEST['inc']) == 'y') { $IncludeMode = true; } if (isset($doIncludeNWS)) { $IncludeMode = $doIncludeNWS; } // end saratoga-weather.org mod //------------------------------------------------------------------------------------------ function fetchUrlWithoutHanging($url,$cacheurl) { global $Status; // Set maximum number of seconds (can have floating-point) to wait for feed before displaying page without feed $numberOfSeconds=4; // Suppress error reporting so Web site visitors are unaware if the feed fails error_reporting(0); // Extract resource path and domain from URL ready for fsockopen $url = str_replace("http://","",$url); $urlComponents = explode("/",$url); $domain = $urlComponents[0]; $resourcePath = str_replace($domain,"",$url); // Establish a connection $socketConnection = fsockopen($domain, 80, $errno, $errstr, $numberOfSeconds); if (!$socketConnection) { $Status .= ""; $html = implode('', file($cacheurl)); return($html); // You may wish to remove the following debugging line on a live Web site } // end if else { $xml = ''; fputs($socketConnection, "GET $resourcePath HTTP/1.0\r\nHost: $domain\r\n\r\n"); // Loop until end of file while (!feof($socketConnection)) { $xml .= fgets($socketConnection, 4096); } // end while fclose ($socketConnection); } // end else return($xml); } // end fetchUrlWithoutHanging function //------------------------------------------------------------------------------------------ // split off Low and High from multiday forecast function split_fcst($fcst) { global $Status; $f = explode(". ",$fcst . ' '); $lowpart = 0; $highpart = 0; foreach ($f as $n => $part) { // find the Low and High sentences if(preg_match('/Low/i',$part)) { $lowpart = $n; } if(preg_match('/High/i',$part)) { $highpart = $n; } } $f[$lowpart] = preg_replace('|(\d+) below|s',"-$1",$f[$lowpart]); $f[$lowpart] = preg_replace('/( above| below| zero)/s','',$f[$lowpart]); $f[$lowpart] .= '.'; $f[$highpart] = preg_replace('|(\d+) below|s',"-$1",$f[$highpart]); $f[$highpart] = preg_replace('/( above| below| zero)/s','',$f[$highpart]); $f[$highpart] .= '.'; $replpart = min($lowpart,$highpart)-1; $fcststr = ''; for ($i=0;$i<=$replpart;$i++) {$fcststr .= $f[$i] . '. '; } // generate static fcst text $fcstLow = $fcststr . ' ' . $f[$lowpart]; $fcstHigh = $fcststr . ' ' . $f[$highpart]; return("$fcstLow\t$fcstHigh"); } //------------------------------------------------------------------------------------------ // function make_icon: parse text and find suitable icon from zone forecast text for period function make_icon($day,$textforecast) { global $Conditions,$Status; if (preg_match('| |i',$day) ) { $icon = "" . preg_replace('| |','
',$day,1) . '

'; } else { $icon = "" . $day . '

'; } $temperature = 'n/a'; $pop = ''; $iconimage = 'na.jpg'; $condition = 'N/A'; if (preg_match('|(\S+) (\d+) percent|',$textforecast,$mtemp)) { // found a PoP // $Status .= "\n"; $pop = $mtemp[2]; } if (preg_match('/(Highs|Lows|Temperatures nearly steady|Temperatures falling to|Temperatures rising to|Near steady temperature) (in the upper|in the lower|in the mid|in the low to mid|in the mid to upper|in the|around|near|nearly|above|below|from) ([\d|-]+)/i',$textforecast,$mtemp)) { // found temp // $Status .= "\n"; if (substr($mtemp[1],0,1) == 'T' or substr($mtemp[1],0,1) == 'N') { // use day for highs/night for lows if 'Temperatures nearly steady' $mtemp[1] = 'Highs'; if (preg_match('|night|i',$day)) { $mtemp[1] = 'Lows'; } } $tcolor = '#FF0000'; if (strtoupper(substr($mtemp[1],0,1)) == 'L') { $tcolor = '#0000FF'; } $temperature = ucfirst(substr($mtemp[1],0,2) . ' '); $t = $mtemp[3]; // the raw temp if (preg_match('/(low to mid|mid to upper|upper|lower|mid|in the)/',$mtemp[2],$ttemp) ) { $t = $t + 5; if ($ttemp[1] == 'upper') { $temperature .= '>' . $t; } if ($ttemp[1] == 'lower') { $temperature .= '<' . $t ; } if ($ttemp[1] == 'mid') { $temperature .= '≈' . $t; } if ($ttemp[1] == 'in the') { $temperature .= '≈' . $t; } if ($ttemp[1] == 'low to mid') { $t = $t -2; $temperature .= '≈' . $t; } if ($ttemp[1] == 'mid to upper') { $t = $t + 2; $temperature .= '≈' . $t; } } if (preg_match('/(near|around)/',$mtemp[2],$ttemp) ) { $temperature .= '≈' . $mtemp[3]; } $temperature .= '°F'; } if (preg_match('/(Highs|Lows) ([\d|-]+) to ([\d|-]+)/i',$textforecast,$mtemp) ) { // temp range forecast $tcolor = '#FF0000'; if (strtoupper(substr($mtemp[1],0,1)) == 'L') { $tcolor = '#0000FF'; } $temperature = ucfirst(substr($mtemp[1],0,2) . ' '); $tavg = sprintf("%0d",round(($mtemp[3] + $mtemp[2]) / 2,0)); $temperature .= '≈' . $tavg . '°F'; } // $Status .= "\n"; // now look for harshest conditions first.. (in order in -data file reset($Conditions); // Do search in load order foreach ($Conditions as $cond => $condrec) { // look for matching condition if(preg_match("!$cond!i",$textforecast,$mtemp)) { list($dayicon,$nighticon,$condition) = explode("\t",$condrec); if (preg_match('|night|i',$day)) { $iconimage = $nighticon . $pop . '.jpg'; } else { $iconimage = $dayicon . $pop . '.jpg'; } break; } } // end of conditions search $icon .= '
' . $condition; return("$icon\t$temperature\t$pop"); } // end make_icons function //------------------------------------------------------------------------------------------ // load the $Conditions array for icon selection based on key phrases function load_cond_data () { global $Conditions, $Status; $Condstring = ' # cond|tornado|nsvrtsra|nsvrtsra|Severe storm| cond|showery or intermittent. Some thunder|scttsra|nscttsra|Showers storms| cond|thunder possible|scttsra|nscttsra|Showers storms| cond|thunder|tsra|ntsra|Thunder storm| cond|rain and sleet|raip|nraip|Rain Sleet| cond|freezing rain and snow|raip|nraip|FrzgRn Snow| cond|rain and snow|rasn|nrasn|Rain and Snow| cond|rain or snow|rasn|nrasn|Rain or Snow| cond|freezing rain|fzra|fzra|Freezing Rain| cond|rain likely|ra|nra|Rain likely| cond|chance of rain|ra|nra|Chance rain| cond|mix|rasn|rasn|Mix| cond|sleet|ip|ip|Sleet| cond|snow|sn|nsn|Snow cond|fog in the morning|sctfg|nbknfg|Fog a.m.| cond|fog after midnight|sctfg|nbknfg|Fog late| cond|fog|fg|nfg|Fog| cond|wind chill down to -|cold|cold|Very Cold| cond|heat index up to 1|hot|hot|Very Hot| cond|overcast|ovc|novc|Overcast| cond|mostly cloudy|bkn|nbkn|Mostly Cloudy| cond|partly cloudy|sct|nsct|Partly Cloudy| cond|cloudy|cloudy|ncloudy|Cloudy| cond|partly sunny|sct|nsct|Partly Sunny| cond|mostly sunny|few|nfew|Mostly Sunny| cond|mostly clear|few|nfew|Mostly Clear| cond|sunny|skc|nskc|Sunny| cond|clear|skc|nskc|Clear| cond|fair|few|nfew|Fair| cond|cloud|bkn|nbkn|Variable Clouds| # '; $config = explode("\n",$Condstring); foreach ($config as $key => $rec) { // load the parser condition strings $recin = trim($rec); if ($recin and substr($recin,0,1) <> '#') { // got a non comment record list($type,$keyword,$dayicon,$nighticon,$condition) = explode('|',$recin . '|||||'); if (isset($type) and strtolower($type) == 'cond' and isset($condition)) { $Conditions["$keyword"] = "$dayicon\t$nighticon\t$condition"; // $Status .= "\n"; } } // end if not comment or blank } // end loading of loop over config recs } // end of load_cond_data function //------------------------------------------------------------------------------------------ if (! $IncludeMode and $PrintMode) { ?> NWS Forecast for <?php echo $forecastcity; ?>
Forecast blank? Force Update

'; } if ($PrintMode) {?>
National Weather Service Forecast for:
Issued by:
Updated:
  $forecasticons[$i]\n"; } ?> $forecasttemp[$i]\n"; } ?>

 

\n"; print "\n"; print "\n"; print "\n"; } ?>
$forecasttitles[$i]
 
$forecasttext[$i]

 

Forecast from NOAA-NWS for .


Accu-Weather Forecast

 


Weather Forecasts | Weather Maps | Weather Radar


Other Harrison County Forecasts

 

For other Harrison County Iowa and surrounding area forecasts
Move point forecast map up, and current conditions, radar, and satellite down.

Click Map for Forecast


Lat/Lon: 41.57 -95.88    Elevation: 1066 ft

Source NOAA