== re-written code (open local test via MAMP) */ global $wf; $wf=new weatherforecast(); class weatherforecast { /* docs: https://open-meteo.com/en/docs */ /* ==================================================================================== for webmaster ================================= */ // develop const develop=true;// false /* ==================================================================================== change these for your location ================ */ // location & time const latitude='39.64'; const longitude='-8.37'; const timezone='Europe/Lisbon';// Europe/Amsterdam /* ==================================================================================== change code below at your own risk ============ */ // weather forecast variables var $days=7;// 1,3,7,14,16 var $prognose=(3*24);//drie dagen hourly forecast var $bars=false; // re-used... var $data=array(); var $datetime; var $dateformatter; // develop var $debug=array(); function __construct() { if(self::develop) { ini_set('display_errors',1); ini_set('display_startup_errors',1); error_reporting(E_ALL); }; date_default_timezone_set(self::timezone); $this->datetime=new DateTime(); $this->dateformatter=new IntlDateFormatter('nl_NL',IntlDateFormatter::FULL,IntlDateFormatter::SHORT,self::timezone,IntlDateFormatter::GREGORIAN); //TODO hiero /* if(isset($_POST['setprefs'])){ echo "treasure will be set if the form has been submitted (to TRUE, I believe)"; } */ $this->callAPI(); } function callAPI() { $current=array( 'temperature_2m', 'relative_humidity_2m', 'apparent_temperature', 'is_day', 'precipitation','rain','showers','snowfall', 'weather_code', 'cloud_cover', 'wind_speed_10m',/* wind_direction_10m */'wind_gusts_10m', ); /* order of variables in daily or hourly is important */ $daily=array( 'weather_code', 'temperature_2m_max','temperature_2m_min','apparent_temperature_max','apparent_temperature_min', 'precipitation_sum','rain_sum','showers_sum','precipitation_hours','precipitation_probability_max','precipitation_probability_min','precipitation_probability_mean', 'sunrise','sunset',//'sunshine_duration','daylight_duration', 'wind_speed_10m_max',/* wind_direction_10m_dominant */'wind_gusts_10m_max', ); $hourly=array( 'temperature_2m', 'relative_humidity_2m', 'apparent_temperature', 'precipitation_probability','precipitation','rain','showers','snowfall', 'weather_code', 'cloud_cover', /* 'visibility', */ 'wind_speed_10m',/* wind_direction_10m */'wind_gusts_10m', 'is_day', ); $url='https://api.open-meteo.com/v1/forecast'. '?latitude='.self::latitude. '&longitude='.self::longitude. '&timezone='.urlencode(self::timezone). '&forecast_days='.$this->days. '¤t='.implode(',',$current). '&daily='.implode(',',$daily). '&hourly='.implode(',',$hourly). '&timeformat=unixtime'; if(self::develop) $this->debug['url']=$url; $ch=curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_FAILONERROR,true);//true to fail verbosely if HTTP code returned greater than or equal to 400, required to be reported via call to curl_error($ch) curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);//true to return transfer as string of return value of curl_exec() instead of outputting it directly curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);//false to stop cURL from verifying peer's certificate, else error "Peer certificate cannot be authenticated with known CA certificates" curl_setopt($ch,CURLOPT_TIMEOUT,5);//untested,standard curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,5);//untested,standard $response=curl_exec($ch); if(curl_errno($ch)) $error=curl_error($ch); curl_close($ch); if(isset($error)) exit('
'.print_r($error,true).'
API url'); if(!$response) exit('
cURL fails...
API url'); $this->data=json_decode($response,true); if(self::develop) $this->debug['data']=$this->data; } function current() { extract($this->data['current']); $neerslag=array(); if($rain) $neerslag[]='regen '.$rain.' mm'; if($showers) $neerslag[]='buien '.$showers.' mm'; if($snowfall) $neerslag[]='sneeuw '.$snowfall.' cm'; $out[]='
'; $out[]='
'.$this->weatherCode($weather_code,$is_day).'
'; $out[]='
'.$this->htmlSymbol('bewolking').$cloud_cover.$this->htmlUnit('bewolking').'
'; $out[]='
'.$this->htmlSymbol('temperatuur').$this->calcTemperature($temperature_2m,$apparent_temperature).$this->htmlUnit('temperatuur').'
'; $out[]='
'.$this->htmlSymbol('neerslag').$this->htmlTooltip($precipitation.$this->htmlUnit('neerslag'),implode('
',$neerslag)).'
'; $out[]='
'.$this->htmlSymbol('wind').$this->htmlWind($wind_speed_10m,$wind_gusts_10m).'
'; $out[]='
'.$this->htmlSymbol('luchtvochtigheid').$relative_humidity_2m.$this->htmlUnit('luchtvochtigheid').'
'; $out[]='
'; $out[]='
'; return $out; } function daily() { extract($this->data['daily']); $out[]='
'; $out[]='

weersverwachting

'; $out[]=''; $out[]=''; $out[]=''; $out[]=''; $out[]=''; // $out[]=''; $out[]=''; $out[]=''; $out[]=''; $out[]=''; $out[]=''; $out[]=''; $out[]=''; foreach($time as $key=>$value) { $datum=explode(' ',$this->formatDate($value)); $out[]=''; $out[]=''; $out[]=''; $out[]=''; $out[]=''; // $out[]=''; $out[]=''; $out[]=''; $tmp=array(); if($precipitation_sum[$key]) { if($rain_sum[$key]) $tmp[]='regen '.$this->formatDecimal($rain_sum[$key]).' mm'; if($showers_sum[$key]) $tmp[]='buien '.$this->formatDecimal($showers_sum[$key]).' mm'; if(isset($snowfall_sum[$key])) $tmp[]='sneeuw '.$this->formatDecimal($snowfall_sum[$key]).' cm'; }; $out[]=''; $out[]=''; $out[]=''; }; $out[]=''; $out[]='
 '.$this->htmlSymbol('zonop').''.$this->htmlSymbol('zonneschijnduur').''.$this->htmlSymbol('zononder').''.$this->htmlSymbol('temperatuur').''.$this->htmlSymbol('neerslag').''.$this->htmlSymbol('wind').'
'.($key==0 ? 'vandaag' : $datum[0]).''.$this->weatherCode($weather_code[$key]).''.$this->formatTime($sunrise[$key],"H:i").''.$this->htmlTooltip(implode('',$this->calcDuration($sunshine_duration[$key])).$this->htmlUnit('u'),'gedurende '.implode('',$this->calcDuration($daylight_duration[$key])).' uur daglicht').''.$this->formatTime($sunset[$key],"H:i").''; $out[]=$this->htmlTooltip( ''.$this->calcTemperature($temperature_2m_min[$key],$apparent_temperature_min[$key]).''.$this->htmlUnit('temperatuur'), 'temperatuur
'.$this->formatDecimal($temperature_2m_min[$key]).$this->htmlUnit('temperatuur').'
gevoelstemperatuur
'.$this->formatDecimal($apparent_temperature_min[$key]).$this->htmlUnit('temperatuur') ); $out[]=$this->htmlTooltip( ''.$this->calcTemperature($temperature_2m_max[$key],$apparent_temperature_max[$key]).''.$this->htmlUnit('temperatuur'), 'temperatuur
'.$this->formatDecimal($temperature_2m_max[$key]).$this->htmlUnit('temperatuur').'
gevoelstemperatuur
'.$this->formatDecimal($apparent_temperature_max[$key]).$this->htmlUnit('temperatuur') ); $out[]='
'.($precipitation_probability_max[$key] ? $this->htmlTooltip( ($precipitation_probability_mean[$key] ? $precipitation_probability_mean[$key].$this->htmlUnit('kans') : $this->htmlNihil()), ($precipitation_probability_min[$key] ? $precipitation_probability_min[$key] : 'geen').' tot '.$precipitation_probability_max[$key].' % kans op neerslag'. ($precipitation_hours[$key] ? '
gedurende '.$precipitation_hours[$key].' uur' : ''). ($tmp ? '
'.implode(', ',$tmp) : '') ) : $this->htmlNihil() ).'
'.$this->htmlWind($wind_speed_10m_max[$key],$wind_gusts_10m_max[$key]).'
'; $out[]='
'; return $out; } function hourly() { extract($this->data['hourly']); $out[]='
'; $out[]='

prognose per uur

'; $out[]=''; $out[]=''; $out[]=''; $i=0; foreach($time as $key=>$value) { if($value>=$this->data['current']['time']) { if(!isset($start)) $start=$key; $end=$key; $out[]=''; ++$i; if($i==$this->prognose) break; }; }; $out[]=''; $out[]=''; $out[]=''; $out[]=''; for($key=$start;$key<=$end;$key++) { $out[]='htmlDayNight($is_day[$key]).' title="'.$this->weatherCode($weather_code[$key],$is_day[$key]).'">'; }; $out[]=''; $out[]=$this->htmlHourlyRow('temperatuur','temperatuur'); $out[]=''; for($key=$start;$key<=$end;$key++) { $out[]='htmlDayNight($is_day[$key]).'>'.$this->calcTemperature($temperature_2m[$key],$apparent_temperature[$key]).''; }; $out[]=''; $out[]=$this->htmlHourlyRow('neerslag','kans'); $out[]=''; for($key=$start;$key<=$end;$key++) { $neerslag=array(); if($rain[$key]) $neerslag[]='regen '.$this->formatDecimal($rain[$key]).' mm'; if($showers[$key]) $neerslag[]='buien '.$this->formatDecimal($showers[$key]).' mm'; if($snowfall[$key]) $neerslag[]='sneeuw '.$this->formatDecimal($snowfall[$key]).' cm'; $out[]='htmlDayNight($is_day[$key]).($neerslag ? ' title="'.implode(', ',$neerslag).'"' : '').'>'.($precipitation_probability[$key] ? $precipitation_probability[$key] : ' ').''; }; $out[]=''; $out[]=$this->htmlHourlyRow('bewolking','bewolking'); $out[]=''; for($key=$start;$key<=$end;$key++) { $out[]='htmlDayNight($is_day[$key]).'>'.($cloud_cover[$key] ? $cloud_cover[$key] : ' ').''; }; $out[]=''; $out[]=$this->htmlHourlyRow('wind','kracht'); $out[]=''; for($key=$start;$key<=$end;$key++) { $out[]='htmlDayNight($is_day[$key]).'>'; $out[]='calcWindstoten($wind_gusts_10m[$key])) ? ' class="windstoten"' : '') .' title="tot windkracht '.$this->calcWindkracht($wind_gusts_10m[$key]).($stoten ? ' met '.$stoten : '') .'">'.(($min=$this->calcWindkracht($wind_speed_10m[$key])) ? $min : ' ').''; $out[]=''; }; $out[]=''; $out[]=$this->htmlHourlyRow('luchtvochtigheid','luchtvochtigheid'); $out[]=''; for($key=$start;$key<=$end;$key++) { $out[]='htmlDayNight($is_day[$key]).'>'.$relative_humidity_2m[$key].''; }; $out[]=''; $out[]=''; $out[]='
htmlDayNight($is_day[$key]).'>'.$this->formatTime($value,"H").'
'; $out[]='
'; return $out; } function barCharts() { /* */ extract($this->data['hourly']); //loop thru data to get start,end,min,max,scale $i=0; foreach($time as $key=>$value) { if($value>=$this->data['current']['time']) { if(!isset($start)) $start=$key; $end=$key; $temperatuur[$key]=$this->calcTemperature($temperature_2m[$key],$apparent_temperature[$key]); $kans[$key]=$precipitation_probability[$key]; ++$i; if($i==$this->prognose) break; }; }; $min=round(min($temperatuur))-1;//for scaling minus 1 $max=round(max($temperatuur))+1;//for scaling plus 1 $scale=ceil($max)-floor($min); $out[]=''; $out[]='
'; for($key=$start;$key<=$end;$key++) { $out[]='
'; $out[]='
'.$this->formatTime($time[$key],"H").'
'; $out[]='
'.$temperatuur[$key].'
'; $out[]='
'; }; $out[]='
'; //kans+neerslag $min=round(min($kans))-1;//for scaling minus 1 $max=round(max($kans))+1;//for scaling plus 1 $scale=ceil($max)-floor($min); $out[]=''; $out[]='
'; for($key=$start;$key<=$end;$key++) { $out[]='
'; $out[]='
'.$this->formatTime($time[$key],"H").'
'; $out[]='
'.$kans[$key].'
'; $out[]='
'; }; $out[]='
'; return $out; } function weatherCode($weather_code,$is_day=1,$key='txt') { /* WMO weather interpretation codes with alternative texts [sometimes day/night dependent] from */ $codes=array( //TODO nl-vertalingen 0 =>array('txt'=>($is_day ? 'zonnig' : 'helder'), 'img'=>'01'),//sunny vs. clear or clear sky 1 =>array('txt'=>'overwegend '.($is_day ? 'zonnig' : 'helder'), 'img'=>'01'),//mainly sunny vs. mainly clear 2 =>array('txt'=>'partly cloudy', 'img'=>'02'),//partly cloudy 3 =>array('txt'=>'bewolkt', 'img'=>'03'),//overcast OR cloudy 45 =>array('txt'=>'mist', 'img'=>'50'),//fog OR foggy 48 =>array('txt'=>'depositing rime fog', 'img'=>'50'),//depositing rime fog OR rime fog 51 =>array('txt'=>'lichte motregen', 'img'=>'09'),//drizzle: light OR light drizzle 53 =>array('txt'=>'motregen', 'img'=>'01'),//drizzle: moderate OR drizzle 55 =>array('txt'=>'dichte motregen', 'img'=>'09'),//drizzle: dense intensity OR heavy drizzle 56 =>array('txt'=>'freezing drizzle: light', 'img'=>'09'),//freezing drizzle: light OR light freezing drizzle 57 =>array('txt'=>'freezing frizzle: dense intensity', 'img'=>'09'),//freezing frizzle: dense intensity OR freezing drizzle 61 =>array('txt'=>'lichte regen', 'img'=>'10'),//rain: slight OR light rain 63 =>array('txt'=>'regen', 'img'=>'10'),//rain: moderate OR rain 65 =>array('txt'=>'zware regen', 'img'=>'10'),//rain: heavy intensity OR heavy rain 66 =>array('txt'=>'freezing rain: light', 'img'=>'10'),//freezing rain: light Or light freezing rain 67 =>array('txt'=>'freezing rain: heavy intensity', 'img'=>'10'),//freezing rain: heavy intensity OR freezing rain 71 =>array('txt'=>'snow fall: slight', 'img'=>'13'),//light snow 73 =>array('txt'=>'snow fall: moderate', 'img'=>'13'),//snow fall: slight OR snow 75 =>array('txt'=>'snow fall: heavy intensity', 'img'=>'13'),//snow fall: heavy intensity oR heavy snow 77 =>array('txt'=>'snow grains', 'img'=>'13'),//snow grains 80 =>array('txt'=>'rain showers: slight', 'img'=>'09'),//rain showers: slight OR light showers 81 =>array('txt'=>'rain showers: moderate', 'img'=>'09'),//rain showers: moderate OR showers 82 =>array('txt'=>'rain showers: violent', 'img'=>'09'),//rain showers: violent OR heavy showers 85 =>array('txt'=>'snow showers: slight', 'img'=>'13'),//snow showers: slight OR light snow showers 86 =>array('txt'=>'snow showers: heavy', 'img'=>'13'),//snow showers: heavy OR snow showers 95 =>array('txt'=>'thunderstorm', 'img'=>'11'),//thunderstorm 96 =>array('txt'=>'thunderstorm with slight hail', 'img'=>'11'),//thunderstorm with slight hail OR light thunderstorms with hail 99 =>array('txt'=>'thunderstorm with heavy hail', 'img'=>'11'),//thunderstorm with heavy hail OR thunderstorm with hail ); return $codes[$weather_code][$key]; } function weatherImageUrl($txt,$is_day=1) { /* source */ if(in_array($txt,array('01','02','10'))) $txt.=($is_day ? 'd' : 'n'); return 'images/weathercodes/'.$txt.'.png'; } function calcDuration($seconds) { $seconds=round($seconds); $hours=floor($seconds/60/60); $remainder=$seconds-($hours*60*60); switch(true) { case $remainder>60*45: $quarter='¾';break; case $remainder>60*30: $quarter='½';break; case $remainder>60*15: $quarter='¼';break; default: $quarter=''; }; return array('hours'=>$hours,'quarter'=>$quarter); } function calcTemperature($temperatuur,$gevoel) { $array=array($temperatuur,$gevoel); $gemiddelde=array_sum($array)/count($array); $afgerond=round($gemiddelde); return $afgerond; } function calcWindkracht($speed) { /* windgemiddelde snelheid over 10 minuten (km/u) */ $speed=(int)$speed; switch(true) { case in_array($speed,range(0,1)): $kracht=0; break; case in_array($speed,range(1,5)): $kracht=1; break; case in_array($speed,range(6,11)): $kracht=2; break; case in_array($speed,range(12,19)): $kracht=3; break; case in_array($speed,range(20,28)): $kracht=4; break; case in_array($speed,range(29,38)): $kracht=5; break; case in_array($speed,range(39,49)): $kracht=6; break; case in_array($speed,range(50,61)): $kracht=7; break; case in_array($speed,range(62,74)): $kracht=8; break; case in_array($speed,range(75,88)): $kracht=9; break; case in_array($speed,range(89,102)): $kracht=10; break; case in_array($speed,range(103,117)): $kracht=11; break; default: $kracht=12; }; return $kracht; } function calcWindstoten($gusts) { /* windstoten zijn kortdurende rukwinden of windvlagen van minstens 50 kilometer per uur vanaf 75 km/u spreken we van zware windstoten en vanaf windkracht 9 spreken we van storm */ $gusts=(int)$gusts; switch(true) { case $gusts>=89: $txt='storm'; break; case $gusts>=75: $txt='zware windstoten'; break; case $gusts>=50: $txt='korte windstoten'; break;// kortdurende rukwinden of windvlagen default: $txt=''; }; return $txt; } function windkracht2Txt($key,$value) { $beaufort=array(//kracht=>benaming,uitwerking boven land en bij mens 0 =>array('benaming'=> 'stil', 'uitwerking'=>'rook stijgt (bijna) recht omhoog'), 1 =>array('benaming'=> 'zwak', 'uitwerking'=>'windrichting goed af te leiden uit rookpluimen'), 2 =>array('benaming'=> 'zwak', 'uitwerking'=>'wind merkbaar in gezicht'), 3 =>array('benaming'=> 'matig', 'uitwerking'=>'stof waait op'), 4 =>array('benaming'=> 'matig', 'uitwerking'=>'haar in war, kleding flappert'), 5 =>array('benaming'=> 'vrij krachtig', 'uitwerking'=>'opwaaiend stof hinderlijk voor ogen, vuilcontainers waaien om'), 6 =>array('benaming'=> 'krachtig', 'uitwerking'=>'paraplu\'s met moeite vast te houden'), 7 =>array('benaming'=> 'hard', 'uitwerking'=>'lastig tegen wind in lopen of fietsen'), 8 =>array('benaming'=> 'stormachtig', 'uitwerking'=>'voortbewegen zeer moeilijk'), 9 =>array('benaming'=> 'storm', 'uitwerking'=>'schoorsteenkappen en dakpannen waaien weg'), 10 =>array('benaming'=> 'zware storm', 'uitwerking'=>'grote schade aan gebouwen, volwassenen waaien om'), 11 =>array('benaming'=> 'zeer zware storm', 'uitwerking'=>'enorme schade aan bossen'), 12 =>array('benaming'=> 'orkaan', 'uitwerking'=>'verwoestingen'), ); return $beaufort[$key][$value]; } function setDatetime($timestamp) { date_timestamp_set($this->datetime,$timestamp); } function formatDate($timestamp) { $this->setDatetime($timestamp); return datefmt_format($this->dateformatter,$this->datetime); } function formatDecimal($str) { return str_replace('.',',',$str); } function formatTime($timestamp,$format) { $this->setDatetime($timestamp); return date_format($this->datetime,$format); } function htmlDayNight($is_day) { return ' class="'.($is_day ? 'day' : 'night').'"'; } function htmlDuration($seconds) { extract($this->calcDuration($seconds)); return ($hours<10 ? ' ' : '').$hours.($quarter ? $quarter : ' '); } function htmlHourlyRow($symbol,$unit) { return ''.$this->htmlSymbol($symbol).$this->htmlUnit($unit).''; } function htmlNihil() { return 'nihil'; } function htmlSymbol($txt) { /* source */ return ''; } function htmlTemperature($temperatuur,$gevoel,$class='') { $array=array($temperatuur,$gevoel); $gemiddelde=array_sum($array)/count($array); $afgerond=round($gemiddelde); $afgerond=(in_array($afgerond,range(-9,9)) ? ' ' : '').$afgerond; $tip='temperatuur
'.$this->formatDecimal($temperatuur).$this->htmlUnit('temperatuur').'
gevoelstemperatuur
'.$this->formatDecimal($gevoel).$this->htmlUnit('temperatuur'); if($class) { return $this->htmlTooltip(''.$afgerond.'',$tip); } else { return $this->htmlTooltip($afgerond.$this->htmlUnit('temperatuur'),$tip); }; } function htmlTooltip($txt,$tip) { //TODO verschillende tooltips (afmeting, alignment enz.) OR title? return ($tip ? ''.$txt.''.$tip.'' : $txt); } function htmlUnit($txt) { $units=array( 'temperatuur' =>'°',//°C 'luchtvochtigheid' =>'%', 'kans' =>'%', 'bewolking' =>'%', 'neerslag' =>'mm', 'regen' =>'mm', 'buien' =>'mm', 'sneeuw' =>'cm', 'zicht' =>'m', 'wind' =>'km/h', 'u' =>'u', 'kracht' =>'kracht', ); return ''.$units[$txt].''; } function htmlWind($speed,$gusts) { $kracht=$this->calcWindkracht($speed); $stoten=$this->calcWindstoten($gusts); return $this->htmlTooltip( $this->windkracht2Txt($kracht,'benaming').($stoten ? '
met '.$stoten.'' : ''), 'windkracht '.$kracht.'
('.$this->windkracht2Txt($kracht,'uitwerking').')' ); } } ?> het weer current()); echo '
'; echo implode('',$wf->daily()); echo '
'; echo implode('',$wf->hourly()); echo '
'; echo implode('',$wf->barCharts()); // if($wf->debug) echo '
'.print_r($wf->debug,true).'
'; ?>