== 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[]=''.$this->formatDate($time).'
';
$out[]=' ';
return $out;
}
function daily() {
extract($this->data['daily']);
$out[]='';
$out[]='weersverwachting ';
$out[]='';
$out[]='';
$out[]='';
$out[]=' ';
$out[]=''.$this->htmlSymbol('zonop').' ';
// $out[]=''.$this->htmlSymbol('zonneschijnduur').' ';
$out[]=''.$this->htmlSymbol('zononder').' ';
$out[]=''.$this->htmlSymbol('temperatuur').' ';
$out[]=''.$this->htmlSymbol('neerslag').' ';
$out[]=''.$this->htmlSymbol('wind').' ';
$out[]=' ';
$out[]=' ';
$out[]='';
foreach($time as $key=>$value) {
$datum=explode(' ',$this->formatDate($value));
$out[]='';
$out[]=''.($key==0 ? 'vandaag ' : $datum[0]).' ';
$out[]=' ';
$out[]=''.$this->weatherCode($weather_code[$key]).' ';
$out[]=''.$this->formatTime($sunrise[$key],"H:i").' ';
// $out[]=''.$this->htmlTooltip(implode('',$this->calcDuration($sunshine_duration[$key])).$this->htmlUnit('u'),'gedurende '.implode('',$this->calcDuration($daylight_duration[$key])).' uur daglicht').' ';
$out[]=''.$this->formatTime($sunset[$key],"H:i").' ';
$out[]='';
$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[]=' ';
$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[]=''.($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()
).' ';
$out[]=''.$this->htmlWind($wind_speed_10m_max[$key],$wind_gusts_10m_max[$key]).' ';
$out[]=' ';
};
$out[]=' ';
$out[]='
';
$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[]='htmlDayNight($is_day[$key]).'>'.$this->formatTime($value,"H").' ';
++$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[]='
';
$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).' ';
?>