<?php
namespace App\Service;
use PDO;
use DateTime;
use GuzzleHttp;
use GuzzleHttp\Client;
use GuzzleHttp\Exception;
use App\Lib\ExcelGenerator;
use App\Service\RedisCache;
use Pimcore\Model\DataObject\Report;
use GuzzleHttp\Exception\RequestException;
use Symfony\Component\HttpFoundation\Response;
use DateTimeZone;
class MeteomaticsWeatherService
{
private $apiBaseUrlOG = MATEOMATICS_API_URL_OG;
private $apiBaseUrl = MATEOMATICS_API_URL;
private $username;
private $password;
private $redisCache;
public function __construct(RedisCache $redisCache)
{
$this->username = MATEOMATICS_API_USERNAME;
$this->password = MATEOMATICS_API_PASSWORD;
$this->redisCache = $redisCache;
}
/**
* Query Meteomatics API for time series data and return the parsed response
*
* @param DateTime $startDate The start date of the time series data
* @param DateTime $endDate The end date of the time series data
* @param string $resolution The time resolution of the data (e.g. PT1H for hourly data)
* @param float $lat The latitude of the location to query data for
* @param float $lon The longitude of the location to query data for
* @param int $hour The number of hours ahead to forecast (e.g. 1 for one hour ahead)
* @param string $format The format to request the data in (e.g. json)
* @return array The parsed response data
*/
public function timeSeriesQueryMeteocache(DateTime $startDate, DateTime $endDate, $resolution, $lat, $lon, $hour, $format)
{
try {
$startDateStr = $startDate->format(DateTime::ISO8601);
$endDateStr = $endDate->format(DateTime::ISO8601);
$parameters = [
'wind_speed_10m:kmh',
'wind_dir_10m:d',
't_2m:C',
'precip_3h:mm',
'weather_symbol_' . $hour . 'h:idx',
'precip_type:idx',
'sunrise:sql',
'wind_speed_10m:kn'
];
$parametersStr = implode(',', $parameters);
// Create unique Redis key
$keyParams = [
$startDate->format(DateTime::ISO8601),
$endDate->format(DateTime::ISO8601),
$resolution,
$lat,
$lon,
$hour,
$format
];
$redisKey = hash('sha256', implode('_', $keyParams));
// Try to get the weather forecast data from Redis cache
$data = $this->redisCache->get($redisKey);
if (!$data) {
$url = "{$this->apiBaseUrl}/{$startDateStr}--{$endDateStr}:{$resolution}/{$parametersStr}/{$lat},{$lon}/" . $format . "?use_decluttered=true";
//echo $url;exit;
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
'connect_timeout' => 2,
'headers' => [
'User-Agent' => 'Meteomatics PHP connector (Guzzle)'
]
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
$parsedData = array();
if (isset($data['data']) && $format == "json") {
foreach ($data['data'] as $item) {
$parameter = $item["parameter"];
$coordinates = $item["coordinates"];
$lat = $coordinates[0]["lat"];
$lon = $coordinates[0]["lon"];
$dates = $coordinates[0]["dates"];
$groupedDates = array();
foreach ($dates as $date) {
$dateTime = new DateTime($date["date"]);
$dateString = $dateTime->format("Y-m-d");
if (!array_key_exists($dateString, $groupedDates)) {
$groupedDates[$dateString] = array();
}
$groupedDates[$dateString][] = $date["value"];
}
$parsedData[$parameter] = array("coordinates" => array("lat" => $lat, "lon" => $lon), "dates" => $groupedDates);
}
} else {
$parsedData = $data;
}
if ($parsedData) {
$this->redisCache->set($redisKey, $parsedData, 86400);
}
} else {
$parsedData = $data;
}
return $parsedData;
} catch (Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
public function createErrorResponse(int $http_code): Response
{
switch ($http_code) {
case 100:
$text = 'Continue';
break;
case 101:
$text = 'Switching Protocols';
break;
case 200:
$text = 'OK';
break;
case 201:
$text = 'Created';
break;
case 202:
$text = 'Accepted';
break;
case 203:
$text = 'Non-Authoritative Information';
break;
case 204:
$text = 'No Content';
break;
case 205:
$text = 'Reset Content';
break;
case 206:
$text = 'Partial Content';
break;
case 300:
$text = 'Multiple Choices';
break;
case 301:
$text = 'Moved Permanently';
break;
case 302:
$text = 'Moved Temporarily';
break;
case 303:
$text = 'See Other';
break;
case 304:
$text = 'Not Modified';
break;
case 305:
$text = 'Use Proxy';
break;
case 400:
$text = 'Bad Request';
break;
case 401:
$text = 'Unauthorized';
break;
case 402:
$text = 'Payment Required';
break;
case 403:
$text = 'Forbidden';
break;
case 404:
$text = 'Not Found';
break;
case 405:
$text = 'Method Not Allowed';
break;
case 406:
$text = 'Not Acceptable';
break;
case 407:
$text = 'Proxy Authentication Required';
break;
case 408:
$text = 'Request Time-out';
break;
case 409:
$text = 'Conflict';
break;
case 410:
$text = 'Gone';
break;
case 411:
$text = 'Length Required';
break;
case 412:
$text = 'Precondition Failed';
break;
case 413:
$text = 'Request Entities Too Large';
break;
case 414:
$text = 'Request-URI Too Large';
break;
case 415:
$text = 'Unsupported Media Type';
break;
case 500:
$text = 'Internal Server Error';
break;
case 501:
$text = 'Not Implemented';
break;
case 502:
$text = 'Bad Gateway';
break;
case 503:
$text = 'Service Unavailable';
break;
case 504:
$text = 'Gateway Time-out';
break;
case 505:
$text = 'HTTP Version not supported';
break;
default:
$text = 'Unknown http status code';
break;
}
$response = new Response();
$response->setContent($text);
$response->setStatusCode($http_code);
$response->headers->set('Content-Type', 'text/plain');
return $response;
}
/**
* Fetches the weather forecast data for a given latitude, longitude, and for selected data range
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param int $days The number of days for which forecast is required
* @return array|null The weather forecast data in JSON format, or null if there was an error
*/
public function getTempratureByParams(array $coordinates, string $startDate, string $endDate, string $parametersStr, int $hour = 1)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('custom_noti_%s_%s_%s', md5(implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates))), ($startDate . '-' . $endDate), $parametersStr . $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
// $coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
// p_r($coordinateString); // Debug
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$parametersStr,
$coordinateString
);
} else {
//p_R($coordinates);
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
// // $startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
// // $endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('custom_noti_%s_%s_%s', md5(implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates))), ($startDate . '-' . $endDate), $parametersStr . $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
//return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$parametersStr,
$latitude,
$longitude
);
//p_r($url);
}
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches the weather forecast data for a given latitude, longitude, and for selected data range
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param int $days The number of days for which forecast is required
* @return array|null The weather forecast data in JSON format, or null if there was an error
*/
public function getForecastData(array $coordinates, string $startDate, string $endDate, int $hours, string $model = "ksancm-wrf-48", $translator)
{
try {
// Set timezone to Saudi (UTC+3)
$timezone = new \DateTimeZone('Asia/Riyadh');
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
// throw new \InvalidArgumentException('Invalid dates');
}
if ($hours < 1 and $hours > 24) {
throw new \InvalidArgumentException('Invalid hour');
}
// $startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
// $endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// // Adjust the date range based on the hours parameter
// if ($hours == 24) {
// $startDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($startDate . ' +1 day'));
// $endDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($endDate . ' +1 day'));
// } elseif ($hours == 1) {
// $startDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($startDate . ' +1 hour'));
// $endDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($endDate . ' +1 hour'));
// }
// Convert dates to Saudi timezone
$startDateObj = new \DateTime($startDate, $timezone);
$endDateObj = new \DateTime($endDate, $timezone);
// Subtract 3 hours from each date
// $startDateObj->modify('-3 hours');
// $endDateObj->modify('-3 hours');
$startDate = $startDateObj->format('Y-m-d\TH:i:s.v\Z');
$endDate = $endDateObj->format('Y-m-d\TH:i:s.v\Z');
// Adjust date range based on the hours parameter
$startDateNew = clone $startDateObj;
$endDateNew = clone $endDateObj;
if ($hours == 24) {
$startDateNew->modify('+1 day');
$endDateNew->modify('+1 day');
} elseif ($hours == 1) {
$startDateNew->modify('+1 hour');
$endDateNew->modify('+1 hour');
}
$startDateNew = $startDateNew->format('Y-m-d\TH:i:s.v\Z');
$endDateNew = $endDateNew->format('Y-m-d\TH:i:s.v\Z');
// Create a Redis key for the cache
$cacheKey = sprintf('daily_forecast_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $model . $hours);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$url1 = sprintf(
'%s/%s--%s:PT%sH/t_max_2m_%sh:C,t_min_2m_%sh:C,t_apparent_min_%sh:C,t_apparent_max_%sh:C/%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$hours,
$hours,
$coordinateString
);
$url2 = sprintf(
'%s/%s--%s:PT%sH/wind_speed_mean_10m_%sh:kmh,wind_dir_mean_10m_%sh:d,prob_precip_%sh:p,precip_%sh:mm,relative_humidity_mean_2m_%sh:p,effective_cloud_cover_mean_%sh:octas,dew_point_mean_2m_%sh:C,wind_gusts_10m_%sh:kmh/%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$coordinateString
);
$url3 = sprintf(
'%s/%s--%s:PT%sH/t_2m:C,visibility:km,wind_gusts_10m_%sh:kn,wind_speed_mean_10m_%sh:kn/%s/json?model=mix&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$coordinateString
);
$url4 = sprintf(
'%s/%s--%s:PT10M/t_2m:C/%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$coordinateString
);
$url5 = sprintf(
'%s/%s--%s:PT3H/precip_3h:mm,prob_precip_3h:p/%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$coordinateString
);
$url6 = sprintf(
'%s/%s--%s:PT6H/precip_6h:mm,prob_precip_6h:p,wind_speed_mean_100m_%sh:kmh,wind_speed_mean_200m_%sh:kmh,wind_speed_mean_300m_%sh:kmh/%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$coordinateString
);
$url7 = sprintf(
'%s/%s--%s:PT6H/wind_gusts_10m:kmh,wind_gusts_20m:kmh,wind_gusts_40m:kmh,wind_gusts_50m:kmh,dust_0p03um_0p55um:ugm3,dust_0p55um_0p9um:ugm3,dust_0p9um_20um:ugm3/%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$coordinateString
);
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if ($hours < 1 and $hours > 24) {
throw new \InvalidArgumentException('Invalid hour');
}
// $startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
// $endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// // Adjust the date range based on the hours parameter
// if ($hours == 24) {
// $startDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($startDate . ' +1 day'));
// $endDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($endDate . ' +1 day'));
// } elseif ($hours == 1) {
// $startDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($startDate . ' +1 hour'));
// $endDateNew = date('Y-m-d\TH:i:s.v\Z', strtotime($endDate . ' +1 hour'));
// }
// Convert dates to Saudi timezone
$startDateObj = new \DateTime($startDate, $timezone);
$endDateObj = new \DateTime($endDate, $timezone);
// Subtract 3 hours from each date
// $startDateObj->modify('-3 hours');
// $endDateObj->modify('-3 hours');
$startDate = $startDateObj->format('Y-m-d\TH:i:s.v\Z');
$endDate = $endDateObj->format('Y-m-d\TH:i:s.v\Z');
// Adjust date range based on the hours parameter
$startDateNew = clone $startDateObj;
$endDateNew = clone $endDateObj;
if ($hours == 24) {
$startDateNew->modify('+1 day');
$endDateNew->modify('+1 day');
} elseif ($hours == 1) {
$startDateNew->modify('+1 hour');
$endDateNew->modify('+1 hour');
}
$startDateNew = $startDateNew->format('Y-m-d\TH:i:s.v\Z');
$endDateNew = $endDateNew->format('Y-m-d\TH:i:s.v\Z');
// Create a Redis key for the cache
$cacheKey = sprintf('daily_forecast_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), ($startDate . '-' . $endDate) . $model . $hours);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url1 = sprintf(
'%s/%s--%s:PT%sH/t_max_2m_%sh:C,t_min_2m_%sh:C,t_apparent_min_%sh:C,t_apparent_max_%sh:C/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$hours,
$hours,
$latitude,
$longitude
);
// print_r($url1);exit;
$url2 = sprintf(
'%s/%s--%s:PT%sH/wind_speed_mean_10m_%sh:kmh,wind_dir_mean_10m_%sh:d,prob_precip_%sh:p,precip_%sh:mm,relative_humidity_mean_2m_%sh:p,effective_cloud_cover_mean_%sh:octas,dew_point_mean_2m_%sh:C,wind_gusts_10m_%sh:kmh/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$hours,
$latitude,
$longitude
);
$url3 = sprintf(
'%s/%s--%s:PT%sH/t_2m:C,visibility:km,wind_gusts_10m_%sh:kn,wind_speed_mean_10m_%sh:kn/%s,%s/json?model=mix&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$latitude,
$longitude
);
$url4 = sprintf(
'%s/%s--%s:PT10M/t_2m:C/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$latitude,
$longitude
);
$url5 = sprintf(
'%s/%s--%s:PT3H/precip_3h:mm,prob_precip_3h:p/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$latitude,
$longitude
);
$url6 = sprintf(
'%s/%s--%s:PT6H/precip_6h:mm,prob_precip_6h:p,wind_speed_mean_100m_%sh:kmh,wind_speed_mean_200m_%sh:kmh,wind_speed_mean_300m_%sh:kmh/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$hours,
$hours,
$hours,
$latitude,
$longitude
);
$url7 = sprintf(
'%s/%s--%s:PT6H/wind_gusts_10m:kmh,wind_gusts_20m:kmh,wind_gusts_40m:kmh,wind_gusts_50m:kmh,dust_0p03um_0p55um:ugm3,dust_0p55um_0p9um:ugm3,dust_0p9um_20um:ugm3/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDateNew,
$endDateNew,
$latitude,
$longitude
);
}
$response = $client->request('GET', $url1, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data1 = json_decode($response->getBody(), true);
// Adjust the dates in the response data
$this->adjustResponseDates($data1['data'], $hours);
$response = $client->request('GET', $url2, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data2 = json_decode($response->getBody(), true);
$this->adjustResponseDates($data2['data'], $hours);
$response = $client->request('GET', $url3, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data3 = json_decode($response->getBody(), true);
$this->adjustResponseDates($data3['data'], $hours);
$response = $client->request('GET', $url4, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data4 = json_decode($response->getBody(), true);
$this->adjustResponseDates($data4['data'], $hours);
$response = $client->request('GET', $url5, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data5 = json_decode($response->getBody(), true);
$this->adjustResponseDates($data5['data'], $hours);
$response = $client->request('GET', $url6, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data6 = json_decode($response->getBody(), true);
$this->adjustResponseDates($data6['data'], $hours);
$response = $client->request('GET', $url7, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data7 = json_decode($response->getBody(), true);
$this->adjustResponseDates($data7['data'], $hours);
$dataFinal = $data1;
$dataFinal['data'] = array_merge($data6['data'], $data5['data'], $data4['data'], $data1['data'], $data2['data'], $data3['data'], $data7['data']);
$weatherSymbols = $this->getWeatherSymbols($coordinates, $startDate, $endDate, 'PT' . $hours . 'H', $hours . 'h', true);
if (isset($weatherSymbols['data'][0]['parameter'])) {
$dataFinal['symbols'] = $weatherSymbols['data'][0];
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $dataFinal);
return $dataFinal;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches the hourly weather forecast data for a given latitude, longitude, and hour
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $hourly The hour for which forecast is required in 24-hour format
* @return array The hourly weather forecast data in JSON format
*/
public function getHourlyForecastData(array $coordinates, string $startDate, string $endDate, int $hour, string $model, $translator)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('hourly_forecast_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $model, $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$url1 = sprintf(
'%s/%s--%s:PT%sH/t_max_2m_1h:C,t_min_2m_1h:C,t_apparent_min_1h:C,t_apparent_max_1h:C,wind_speed_mean_10m_1h:kn,wind_gusts_10m_1h:kn/%+%/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$coordinateString,
$coordinateString
);
$url2 = sprintf(
'%s/%s--%s:PT%sH/wind_speed_mean_10m_1h:kmh,wind_dir_mean_10m_1h:d,prob_precip_1h:p,precip_1h:mm,relative_humidity_mean_2m_1h:p,visibility:km,effective_cloud_cover_mean_1h:octas,dew_point_mean_2m_1h:C,wind_gusts_10m_1h:kmh/%+%/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$coordinateString,
$coordinateString
);
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('hourly_forecast_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), ($startDate . '-' . $endDate) . $model, $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url1 = sprintf(
'%s/%s--%s:PT%sH/t_max_2m_1h:C,t_min_2m_1h:C,t_apparent_min_1h:C,t_apparent_max_1h:C,wind_speed_mean_10m_1h:kn,wind_gusts_10m_1h:kn/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$latitude,
$longitude
);
$url2 = sprintf(
'%s/%s--%s:PT%sH/wind_speed_mean_10m_1h:kmh,wind_dir_mean_10m_1h:d,prob_precip_1h:p,precip_1h:mm,relative_humidity_mean_2m_1h:p,visibility:km,effective_cloud_cover_mean_1h:octas,dew_point_mean_2m_1h:C,wind_gusts_10m_1h:kmh/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$latitude,
$longitude
);
}
$response = $client->request('GET', $url1, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data1 = json_decode($response->getBody(), true);
$response = $client->request('GET', $url2, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data2 = json_decode($response->getBody(), true);
$data3 = $data1;
$data3['data'] = array_merge($data1['data'], $data2['data']);
$weatherSymbols = $this->getWeatherSymbols($coordinates, $startDate, $endDate, 'PT1H', '1h');
if (isset($weatherSymbols['data'][0]['parameter'])) {
$data3['symbols'] = $weatherSymbols['data'][0];
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data3);
return $data3;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches the hourly weather forecast data for a given latitude, longitude, and hour
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $hourly The hour for which forecast is required in 24-hour format
* @return array The hourly weather forecast data in JSON format
*/
public function getForecastDataHistoryHourly(array $coordinates, string $startDate, string $endDate, $translator, int $hour = 1)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('historical_hourly_forecast_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)), $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$url1 = sprintf(
'%s/%s--%s:PT%sH/sfc_pressure:hPa,msl_pressure:hPa,dew_point_1000hPa:C,relative_humidity_2m:p,t_max_2m_1h:C,t_min_2m_1h:C,wind_speed_10m:kmh,wind_dir_10m:d,precip_1h:mm/%s+%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$coordinateString,
$coordinateString
);
$url2 = sprintf(
'%s/%s--%s:PT%sH/effective_cloud_cover:octas,dew_point_2m:C,wind_speed_mean_10m_1h:ms,wind_speed_10m:kn/%s+%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$coordinateString,
$coordinateString
);
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
// 2023-04-06T00:00:00.000Z--2023-04-07T00:00:00.000Z
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('historical_hourly_forecast_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)), $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url1 = sprintf(
'%s/%s--%s:PT%sH/sfc_pressure:hPa,msl_pressure:hPa,dew_point_1000hPa:C,relative_humidity_2m:p,t_max_2m_1h:C,t_min_2m_1h:C,wind_speed_10m:kmh,wind_dir_10m:d,precip_1h:mm/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$latitude,
$longitude
);
$url2 = sprintf(
'%s/%s--%s:PT%sH/sfc_pressure:hPa,msl_pressure:hPa,dew_point_1000hPa:C,relative_humidity_2m:p,t_max_2m_1h:C,t_min_2m_1h:C,wind_speed_10m:kmh,wind_dir_10m:d,precip_1h:mm,wind_speed_10m:kn/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$latitude,
$longitude
);
//echo $url;exit;
}
$response = $client->request('GET', $url1, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data1 = json_decode($response->getBody(), true);
$response = $client->request('GET', $url2, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data2 = json_decode($response->getBody(), true);
array_push($data1['data'], $data2['data']);
$weatherSymbols = $this->getWeatherSymbols($coordinates, $startDate, $endDate, 'PT1H', $hour . 'h');
if (isset($weatherSymbols['data'][0]['parameter'])) {
$data1['symbols'] = $weatherSymbols['data'][0];
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data1);
return $data1;
} catch (GuzzleHttp\Exception\RequestException $e) {
//p_r($e->getMessage());exit;
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
//p_r($e->getMessage());exit;
return throw new \Exception($e->getMessage());
}
}
/**
* Compare weather based on mateomatics models
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $hourly The hour for which forecast is required in 24-hour format
* @return array The hourly weather forecast data in JSON format
*/
public function getCompareParameters(array $coordinates, string $startDate, string $endDate, string $model, string $tempParam, string $timeDuration = "P1H", $translator)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('compare_model_%s_%s_' . $model . '_' . $tempParam, implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $timeDuration);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$url = sprintf(
'%s/%s--%s:%s/%s/%+%/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$timeDuration,
$tempParam,
$coordinateString,
$coordinateString
);
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => true, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => true, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => true, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('compare_model_%s_%s_' . $model . '_' . $tempParam, implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $timeDuration);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:%s/%s/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$timeDuration,
$tempParam,
$latitude,
$longitude
);
}
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Get forecast data in daily dashboard display for multiple locations
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param int $days The number of days for which forecast is required
* @return array The model forecast data
*/
public function getDashboardDailyForecast(array $coordinates, string $startDate, string $endDate)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('dashboard_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$url = sprintf(
'%s/%s--%s:P%sD/t_max_2m_24h:C,t_apparent:C,wind_speed_10m:kmh,wind_dir_mean_10m_24h:d,prob_precip_24h:p,precip_24h:mm,sunrise:sql,visibility:km,wind_speed_10m:kn/%+%/json?use_decluttered=true',
$this->apiBaseUrl,
$endDate,
$startDate,
1,
$coordinateString,
$coordinateString
);
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('dashboard_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:P%sD/t_max_2m_24h:C,t_apparent:C,wind_speed_10m:kmh,wind_dir_mean_10m_24h:d,prob_precip_24h:p,precip_24h:mm,sunrise:sql,visibility:km,wind_speed_10m:kn/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$endDate,
$startDate,
1,
$latitude,
$longitude
);
}
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Get forecast data for the provided coordinates
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $timestamp The timestamp for which forecast is required in the format "YYYY-MM-DDTHHZ"
* @param string $duration The duration for which forecast is required in ISO 8601 format "P1D" for 1 day, "PT1H" for 1 hour
* @param string $parameters The weather parameters to fetch separated by comma, e.g. "t_2m:C,sfc_pressure:hPa,wind_speed_10m:ms"
* @param string $aggregations The aggregations to apply to the fetched parameters separated by comma, e.g. "mean,sum"
* @param string $format The format in which to receive the data, either "json" or "xml"
*
* @return array The forecast data for the provided coordinates
*/
public function getForecastForCoordinates(
array $coordinates,
string $timestamp,
string $duration,
string $parameters,
string $aggregations,
string $format
) {
try {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (!is_array($coordinate) || count($coordinate) !== 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}Z$/', $timestamp)) {
throw new \InvalidArgumentException('Invalid timestamp');
}
if (!in_array($duration, ['PT1H', 'P1D'])) {
throw new \InvalidArgumentException('Invalid duration');
}
if (!is_string($parameters) || empty($parameters)) {
throw new \InvalidArgumentException('Invalid parameters');
}
if (!is_string($aggregations) || empty($aggregations)) {
throw new \InvalidArgumentException('Invalid aggregations');
}
if (!in_array($format, ['json', 'xml'])) {
throw new \InvalidArgumentException('Invalid format');
}
// Convert the coordinates array into a string
$coordinatesString = implode('_', array_map(function ($coordinate) {
return implode(',', $coordinate);
}, $coordinates));
// Build the URL for the API call
$url = sprintf(
'%s/%s/%s/%s/%s/%s/%s.%s?use_decluttered=true',
$this->apiBaseUrl,
$timestamp,
$duration,
$parameters,
$coordinatesString,
$aggregations,
$format
);
// Make the API call
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Get weather symbols
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param int $days The number of days for which forecast is required
* @return array The model forecast data
*/
public function getWeatherSymbols(array $coordinates, string $startDate, string $endDate, string $weatherFirstParam = 'PT1H', string $weatherSecondParam = '1h', $adjustDate = false)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
if ($adjustDate) {
// Adjust the date range based on the hours parameter
if ($weatherSecondParam == '24h') {
$startDate = date('Y-m-d\TH:i:s.v\Z', strtotime($startDate . ' +1 day'));
$endDate = date('Y-m-d\TH:i:s.v\Z', strtotime($endDate . ' +1 day'));
} elseif ($weatherSecondParam == '1h') {
$startDate = date('Y-m-d\TH:i:s.v\Z', strtotime($startDate . ' +1 hour'));
$endDate = date('Y-m-d\TH:i:s.v\Z', strtotime($endDate . ' +1 hour'));
} elseif ($weatherSecondParam == '12h') {
$startDate = date('Y-m-d\TH:i:s.v\Z', strtotime($startDate . ' +12 hour'));
$endDate = date('Y-m-d\TH:i:s.v\Z', strtotime($endDate . ' +12 hour'));
}
}
// Create a Redis key for the cache
$cacheKey = sprintf('get_symbols_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $weatherFirstParam);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:%s/weather_symbol_%s:idx/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$weatherFirstParam,
$weatherSecondParam,
$latitude,
$longitude
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($adjustDate) {
// Define your adjustment ('-1 day' or '-1 hour' or '-12 hour')
if ($weatherSecondParam == '24h') {
$timeAdjustment = 24;
} elseif ($weatherSecondParam == '1h') {
$timeAdjustment = 1;
} elseif ($weatherSecondParam == '12h') {
$timeAdjustment = 12;
}
// Adjust the dates in the response data
$this->adjustResponseDates($data['data'], $timeAdjustment);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Weather Map
*
* @param string $version The version of the API (e.g., '1.3.0')
* @param string $request The type of request (e.g., 'GetMap')
* @param string $layers The layers to include in the map
* @param string $crs The coordinate reference system (e.g., 'EPSG:3857')
* @param string $bBox The bounding box in the format 'minX,minY,maxX,maxY'
* @param string $format The format of the map image (e.g., 'image/png')
* @param int $width The width of the map image
* @param int $height The height of the map image
* @param bool $tiled Whether to use tiled rendering (default: true)
* @return array The model forecast data
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getWeatherMap(
string $version,
string $request,
string $layers,
string $crs,
string $bBox,
string $format,
int $width,
int $height,
bool $tiled = true
) {
// Validate data types of input parameters
if (!is_string($version)) {
throw new \InvalidArgumentException('Invalid data type for $version. Expected string.');
}
if (!is_string($request)) {
throw new \InvalidArgumentException('Invalid data type for $request. Expected string.');
}
if (!is_string($layers)) {
throw new \InvalidArgumentException('Invalid data type for $layers. Expected string.');
}
if (!is_string($crs)) {
throw new \InvalidArgumentException('Invalid data type for $crs. Expected string.');
}
if (!is_string($bBox)) {
throw new \InvalidArgumentException('Invalid data type for $bBox. Expected string.');
}
if (!is_string($format)) {
throw new \InvalidArgumentException('Invalid data type for $format. Expected string.');
}
if (!is_int($width)) {
throw new \InvalidArgumentException('Invalid data type for $width. Expected int.');
}
if (!is_int($height)) {
throw new \InvalidArgumentException('Invalid data type for $height. Expected int.');
}
if (!is_bool($tiled)) {
throw new \InvalidArgumentException('Invalid data type for $tiled. Expected bool.');
}
try {
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/wms?VERSION=%s&REQUEST=%s&LAYERS=%s&CRS=%s&BBOX=%s&FORMAT=%s&WIDTH=%s&HEIGHT=%s&TILED=%s&use_decluttered=true',
$this->apiBaseUrl,
$version,
$request,
$layers,
$crs,
$bBox,
$format,
$width,
$height,
$tiled
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
return $response->getBody();
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Weather Warnings
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $warningParam The type of weather warning parameter (default: 'frost_warning')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getWeatherWarnings(array $coordinates, string $startDate, string $endDate, string $duration = '24', string $warningParam = 'frost_warning', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
// throw new \InvalidArgumentException('Coordinates should be a non-empty array');
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
// throw new \InvalidArgumentException('Duration should be numeric');
return ["success" => false, "message" => $translator->trans("duration_should_be _numeric")];
}
$weatherWarning = new \Pimcore\Model\DataObject\MMWarningConfig\Listing();
$weatherWarning->setCondition("WarningKey = ? AND (hourEnd >= ? AND hourStart <= ?)", [$warningParam, $duration, $duration]);
$weatherWarning = $weatherWarning->load();
if (!$weatherWarning) {
throw new \Exception('Weather configuration is missing for key.' . $warningParam);
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('weather_warning_%s_%s_%s', $warningParam . $format, implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH//%s_%sh:idx/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$warningParam,
$duration,
$latitude,
$longitude
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
$modifiedParams = [];
if (isset($data['data'][0]['coordinates'][0]['dates'])) {
foreach ($data['data'][0]['coordinates'][0]['dates'] as $weather) {
$data = \App\Lib\Utility::getWeatherTypeDescription($weatherWarning[0]->getParams(), $weather);
$modifiedParams[] = $data;
}
}
$data['data'] = $modifiedParams;
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Weather Warnings
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $warningParam The type of weather warning parameter (default: 'frost_warning')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getPrecipitationType(array $coordinates, string $startDate, string $endDate, string $duration = '24', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
// throw new \InvalidArgumentException('Coordinates should be a non-empty array');
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
// throw new \InvalidArgumentException('Duration should be numeric');
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('weather_precitipitation_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
// return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sM/precip_type:idx/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$latitude,
$longitude
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
$modifiedParams = [];
if (isset($data['data'][0]['coordinates'][0]['dates'])) {
foreach ($data['data'][0]['coordinates'][0]['dates'] as $prepData) {
$data = \App\Lib\Utility::getPrecipitationTypeDescription($prepData);
$modifiedParams[] = $data;
}
} else {
throw new \Exception("Data not available");
}
$data['data'][0]['coordinates'][0]['dates'] = $modifiedParams;
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Weather Warnings
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'min')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getHailIndex(array $coordinates, string $startDate, string $endDate, string $duration = '24', string $intervalType = "min", string $format = "json", $translator)
{
try {
// Validate the input parameters
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("duration_dates")];
}
if (!is_numeric($duration)) {
// throw new \InvalidArgumentException('Duration should be numeric');
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('weather_hail_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration . $intervalType));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
//10min, 20min, 30min, 1h, 3h, 6h, 12h, 24h
// If cache is empty, get the data from the API
if ($intervalType == "min") {
$url = sprintf(
'%s/%s--%s:PT%sM/hail_%smin:cm/%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$coordinateString
);
} else if ($intervalType == "hour") {
$url = sprintf(
'%s/%s--%s:PT%sH/hail_%sh:cm/%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$coordinateString
);
}
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("duration_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("duration_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("duration_dates")];
}
if (!is_numeric($duration)) {
// throw new \InvalidArgumentException('Duration should be numeric');
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('weather_hail_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration . $intervalType));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
//10min, 20min, 30min, 1h, 3h, 6h, 12h, 24h
// If cache is empty, get the data from the API
if ($intervalType == "min") {
$url = sprintf(
'%s/%s--%s:PT%sM/hail_%smin:cm/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$latitude,
$longitude
);
} else if ($intervalType == "hour") {
$url = sprintf(
'%s/%s--%s:PT%sH/hail_%sh:cm/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$latitude,
$longitude
);
}
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Temprature
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
//https://api.meteomatics.com/2023-07-11T00:00:00Z--2023-07-14T00:00:00Z:PT1H/t_2m:C/48.8566,2.3522/json
public function getTemprature(array $coordinates, string $startDate, string $endDate, string $duration = '24', string $intervalType = "hour", string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinate")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
// throw new \InvalidArgumentException('Coordinates should be a non-empty array');
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_coordinate")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
// throw new \InvalidArgumentException('Duration should be numeric');
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('temprature_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration . $intervalType));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
if ($intervalType == "hour") {
$url = sprintf(
'%s/%s--%s:PT%sM/t_2m:C/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$latitude,
$longitude
);
} else if ($intervalType == "day") {
$url = sprintf(
'%s/%s--%s:P%sD/t_2m:C/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$latitude,
$longitude
);
}
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Precipitation Probability
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
//https://api.meteomatics.com/2023-07-11T00:00:00Z--2023-07-14T00:00:00Z:PT1H/t_2m:C/48.8566,2.3522/json
public function getPrecipitationProbability(array $coordinates, string $startDate, string $endDate, string $duration = '24', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinate")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
// throw new \InvalidArgumentException('Duration should be numeric');
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('precep_prob_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/prob_precip_%sh:p/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Visibility
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getVisibility(array $coordinates, string $startDate, string $endDate, string $duration = '24', $unit = 'km', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
// throw new \InvalidArgumentException('Coordinates should be a non-empty array');
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
// throw new \InvalidArgumentException('Invalid dates');
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
// throw new \InvalidArgumentException('Duration should be numeric');
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
if (!in_array($unit, ['m', 'km', 'ft', 'nmi'])) {
// throw new \InvalidArgumentException('Invalid unit');
return ["success" => false, "message" => $translator->trans("invalid_unit")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('visibility_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/visibility:%s/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$unit,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Wind Direction
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
//https://api.meteomatics.com/2023-07-11T00:00:00ZP2D:PT3H/wind_dir_10m:d,wind_dir_700hPa:d/47.412164,9.340652/csv
public function getWindDirection(array $coordinates, string $startDate, string $endDate, string $duration = '24', $height = '10m', $level = '700hPa', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
if (!in_array($level, ['1000hPa', '950hPa', '925hPa', '900hPa', '850hPa', '800hPa', '700hPa', '500hPa', '300hPa', '250hPa', '200hPa', '150hPa', '100hPa', '70hPa', '50hPa', '10hPa'])) {
return ["success" => false, "message" => $translator->trans("invalid_level")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('wind_direction_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration . $level));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/wind_dir_%s:d,wind_dir_%s:d/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$height,
$level,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Wind Speed
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getWindSpeed(array $coordinates, string $startDate, string $endDate, string $duration = '24', $unit = 'ft', $level = '700hPa', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
if (!in_array($level, ['1000hPa', '950hPa', '925hPa', '900hPa', '850hPa', '800hPa', '700hPa', '500hPa', '300hPa', '250hPa', '200hPa', '150hPa', '100hPa', '70hPa', '50hPa', '10hPa'])) {
return ["success" => false, "message" => $translator->trans("invalid_level")];
}
if (!in_array($unit, ['ms', 'kmh', 'mph', 'kn', 'bft'])) {
return ["success" => false, "message" => $translator->trans("invalid_unit")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('wind_speed_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration . $unit . $level));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/wind_speed_%s:%s/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$level,
$unit,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Slippery Road
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getSlipperyRoad(array $coordinates, string $startDate, string $endDate, string $duration = '24', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('slipary_road_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/prob_slippery_road_%sh:p,is_slippery_road_%sh:idx/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$duration,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Solar Radiation
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getSolarRadiation(array $coordinates, string $startDate, string $endDate, $translator, string $format = 'png',)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude1 = $coordinates[0][0] ?? null;
$longitude1 = $coordinates[0][1] ?? null;
$latitude2 = $coordinates[1][0] ?? null;
$longitude2 = $coordinates[1][1] ?? null;
if (!is_numeric($latitude1) || $latitude1 < -90 || $latitude1 > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude1) || $longitude1 < -180 || $longitude1 > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (!is_numeric($latitude2) || $latitude2 < -90 || $latitude2 > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (
!is_numeric($longitude2) || $longitude2 < -180 || $longitude2 > 180
) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$url = sprintf(
'%s/%s/global_rad:W/%s,%s_%s,%s:600x400/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$latitude1,
$longitude1,
$latitude2,
$longitude2,
$format
);
// echo $url;
// exit;
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
return $response->getBody();
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Humidity
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getHumidity(array $coordinates, string $startDate, string $endDate, string $duration = '24', $unit = 'ft', $level = '700hPa', string $format = "json", $translator)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
if (!in_array($level, ['1000hPa', '950hPa', '925hPa', '900hPa', '850hPa', '800hPa', '700hPa', '500hPa', '300hPa', '250hPa', '200hPa', '150hPa', '100hPa', '70hPa', '50hPa', '10hPa'])) {
return ["success" => false, "message" => $translator->trans("invalid_level")];
}
if (!in_array($unit, ['p'])) {
return ["success" => false, "message" => $translator->trans("invalid_unit")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('humidity_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration . $unit . $level));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/relative_humidity_%s:%s/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$level,
$unit,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Fog
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The start date for the forecast
* @param string $interval Hours gap between search results
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getFog(array $coordinates, string $startDate, string $endDate, string $interval = '1', $unit = 'km', $translator, string $format = "json")
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($interval)) {
return ["success" => false, "message" => $translator->trans("interval_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('visibility:%s,is_fog_%sh:idx', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . $endDate . $interval . $unit));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/visibility:%s,is_fog_%sh:idx/%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$interval,
$unit,
$interval,
$coordinateString
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($interval)) {
return ["success" => false, "message" => $translator->trans("interval_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('visibility:%s,is_fog_%sh:idx', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . $endDate . $interval . $unit));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/visibility:%s,is_fog_%sh:idx/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$interval,
$unit,
$interval,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Icing Potential
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $interval gap between duration
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getIcingPotential(array $coordinates, string $startDate, string $duration = '24', $interval = '1', $level = '300hPa', $translator, string $format = "json")
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
if (!is_numeric($interval)) {
return ["success" => false, "message" => $translator->trans("interval_should_be_numeric")];
}
if (!in_array($level, ['1000hPa', '975hPa', '950hPa', '925hPa', '900hPa', '875hPa', '850hPa', '825hPa', '800hPa', '775hPa', '750hPa', '700hPa', '650hPa', '600hPa', '550hPa', '500hPa', '450hPa', '400hPa', '350hPa', '300hPa'])) {
return ["success" => false, "message" => $translator->trans("invalid_level")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('icing_potential_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . $duration . $interval . $level));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
//https://api.meteomatics.com/2023-07-22T00:00:00ZP5D:PT1H/icing_potential_300hPa:idx,icing_potential_500hPa:idx,icing_potential_800hPa:idx/47.457625,8.555272/html
$url = sprintf(
'%s/%sP%sD:PT%sH/icing_potential_%s:idx/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$duration,
$interval,
$level,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Wind Gust
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $interval Gap between duration
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
//https://api.meteomatics.com/2023-07-11T00:00:00ZP2D:PT3H/wind_dir_10m:d,wind_dir_700hPa:d/47.412164,9.340652/csv
public function getWindGust(array $coordinates, string $startDate, string $duration = '24', string $interval = '1', $height = '100', $translator, string $format = "json")
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
if (!in_array($duration, ['1', '3', '6', '12', '24'])) {
return ["success" => false, "message" => $translator->trans("invalid_duration")];
}
if (!is_numeric($interval)) {
return ["success" => false, "message" => $translator->trans("interval_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('wind_gusts_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . $duration . $interval));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
// https://api.meteomatics.com/2023-07-22T00:00:00ZP4D:PT3H/wind_speed_mean_100m_3h:ms,wind_gusts_100m_3h:ms/47.412164,9.340652/html
$url = sprintf(
'%s/%sP%sD:PT%sH/wind_gusts_%s_%sh:ms/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$duration,
$interval,
$height,
$interval,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Lightning Strikes
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getLightningStrikes(array $coordinates)
{
try {
// Validate the input parameters
if (empty($coordinates)) {
throw new \InvalidArgumentException('Invalid coordinates');
}
// Create a Redis key for the cache
$cacheKey = sprintf('lighting_strikes_%s', implode('_', array_map(function ($coordinate) {
return $coordinate;
}, $coordinates)));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
// return $cachedData;
}
// If cache is empty, get the data from the API
// https://api.meteomatics.com/wfs?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=lightnings&BBOX=5.77,45.74,10.65,47.89
$url = sprintf(
'%s/wfs?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=lightnings&BBOX=%s&use_decluttered=true',
$this->apiBaseUrl,
implode(",", $coordinates)
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = $response->getBody();
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches Turbulence data from the API or cache
*
* @param string $datetime The date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @return mixed The Turbulence data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getTurbulenceData(string $datetime)
{
try {
// Validate the input parameter
if (empty($datetime)) {
throw new \InvalidArgumentException('Invalid datetime');
}
$datetime = date('Y-m-d\TH:i:s.v\Z', (strtotime($datetime)));
// Create a Redis key for the cache
$cacheKey = sprintf('turbulence_%s', $datetime);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
//return $cachedData;
}
$client = new Client(['verify' => false]);
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s/turbulence_cape:m23s/global:1,1/html_map?use_decluttered=true',
$this->apiBaseUrl,
$datetime
);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches SIGMET data from the API or cache
*
* @param string $datetime The date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @return mixed The SIGMET data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getSigmetData(string $datetime, $translator)
{
try {
// Validate the input parameter
if (empty($datetime)) {
return ["success" => false, "message" => $translator->trans("invalid_datetime")];
}
$datetime = date('Y-m-d\TH:i:s.v\Z', (strtotime($datetime)));
// Create a Redis key for the cache
$cacheKey = sprintf('sigmet_%s', $datetime);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/mvt/aviation_reports/sigmet:0/style.json?datetime=%s&use_decluttered=true',
$this->apiBaseUrl,
$datetime
);
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches Geopotential Height data from the API or cache
*
* @param array $coordinates The coordinates value
* @param string $startDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param string $endDate The end date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param float $level The level value
* @param float $interval The interval value
* @return mixed The Geopotential Height data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getGeopotentialHeightData(array $coordinates, string $startDate, string $endDate, string $level, string $interval, $translator)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];;
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
if (!is_numeric($interval)) {
return ["success" => false, "message" => $translator->trans("interval_should_be_numeric")];
}
if (!in_array($level, ['1000hPa', '950hPa', '925hPa', '900hPa', '850hPa', '800hPa', '700hPa', '500hPa', '300hPa', '250hPa', '200hPa', '150hPa', '100hPa', '70hPa', '50hPa', '10hPa'])) {
return ["success" => false, "message" => $translator->trans("invalid_level")];
}
// Create a Redis key for the cache
$cacheKey = sprintf('geopotential_height_%s_%s_%.6f_%.6f', $startDate, $endDate, $latitude, $longitude);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
//https://api.meteomatics.com/2023-07-23T00:00:00Z--2023-07-26T00:00:00Z:PT1H/geopotential_height_500hPa:m/46.5468,7.9826/html
$url = sprintf(
'%s/%s--%s:PT%sH/geopotential_height_%s:m/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$interval,
$level,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Pressure at Higher Altitudes data from the API or cache
*
* @param array $coordinates The coordinates value
* @param string $startDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param string $endDate The end date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param float $level The level value
* @param float $interval The interval value
* @return mixed The Geopotential Height data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getPressureData(array $coordinates, string $startDate, string $endDate, string $level, string $interval)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
if (!is_numeric($interval)) {
throw new \InvalidArgumentException('Interval should be numeric');
}
if ($level < 1 && $level > 20000) {
throw new \InvalidArgumentException('Invalid level it should be between 1 to 20000');
}
// Create a Redis key for the cache
$cacheKey = sprintf('pressure_%s_%s_%.6f_%.6f', $startDate, $endDate, $latitude, $longitude);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
///pressure_1000m:hPa/-16.489689,-68.119293/html
$url = sprintf(
'%s/%s--%s:PT%sH/pressure_%sm:hPa/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$interval,
$level,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Cloud Cover data from the API or cache
*
* @param array $coordinates The coordinates value
* @param string $startDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param string $endDate The end date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param float $level The level value
* @param float $interval The interval value
* @return mixed The Geopotential Height data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getCloudCover(array $coordinates, string $startDate, string $endDate, $translator)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('cloud_cover_%s_%s_%.6f_%.6f', $startDate, $endDate, $latitude, $longitude);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s/effective_cloud_cover:octas/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Wind Speed vertical components data from the API or cache
*
* @param array $coordinates The coordinates value
* @param string $startDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param string $endDate The end date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param int $level The day value
* @param string $level The level value
* @param string $unit The level value
* @param intervalInMinutes $interval The interval value
* @return mixed The Geopotential Height data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getWindSpeedVerticalComponents(array $coordinates, string $startDate, int $day, int $intervalInMinutes, string $level, string $unit, $translator)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
if (!is_numeric($day)) {
return ["success" => false, "message" => $translator->trans("day_should_be_numeric")];
}
if (!is_numeric($intervalInMinutes)) {
return ["success" => false, "message" => $translator->trans("interval_in_minute_should_be_numeric")];
}
if (!in_array($level, ['1000hPa', '950hPa', '925hPa', '900hPa', '850hPa', '800hPa', '700hPa', '500hPa', '300hPa', '250hPa', '200hPa', '150hPa', '100hPa', '70hPa'])) {
return ["success" => false, "message" => $translator->trans("invalid_level")];
}
// Create a Redis key for the cache
$cacheKey = sprintf('wind_speed_vertical_%s_%s_%s_%s_%.6f_%.6f', $startDate, $day, $level, $unit, $latitude, $longitude);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%sP%sD:PT%sM/wind_speed_w_%s:%s/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$day,
$intervalInMinutes,
$level,
$unit,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Wind Power data from the API or cache
* @param array $coordinates The coordinates value
* @param string $startDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param string $endDate The end date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param int $intervalInMinutes The interval value
* @param int $height The height value
* @param float $unit The interval value
* @return mixed The Geopotential Height data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getWindPower(array $coordinates, string $startDate, string $endDate, int $height, int $intervalInMinutes, string $unit, string $turbine_id, $translator)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
if (!is_numeric($intervalInMinutes)) {
return ["success" => false, "message" => $translator->trans("interval_should_be_numeric")];
}
if (!is_numeric($height)) {
return ["success" => false, "message" => $translator->trans("height_should_be_numeric")];
}
// Create a Redis key for the cache
$cacheKey = sprintf('wind_power_%s_%s_%s_%s_%s', $startDate, $endDate, $height, $unit, $intervalInMinutes);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sM/wind_power_turbine_%s_hub_height_%sm:%s,wind_power_turbine_siemens_swt_2_3_93_2300_hub_height_%sm:%s,wind_power_turbine_enercon_e66_2000_hub_height_%sm:%s/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$intervalInMinutes,
$turbine_id,
$height,
$unit,
$height,
$unit,
$height,
$unit,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Radiation data from the API or cache
* @param array $coordinates The coordinates value
* @param string $startDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param int $intervalInHours The interval value
* @param int $day The day value
* @param string $typeOfRadiation should be one of these "clear_sky_rad","diffuse_rad","direct_rad","global_rad"
* @return mixed The Geopotential Height data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getRadiation(array $coordinates, string $startDate, int $day, int $intervalInHours, string $typeOfRadiation, $translator)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
if (!is_numeric($intervalInHours)) {
return ["success" => false, "message" => $translator->trans("interval_in_hour_should_be_numeric")];
}
if (!is_numeric($day)) {
return ["success" => false, "message" => $translator->trans("day_should_be_numeric")];
}
if (!in_array($typeOfRadiation, ["clear_sky_rad", "diffuse_rad", "direct_rad", "global_rad"])) {
// throw new \InvalidArgumentException('Radiation type should be one of these "clear_sky_rad","diffuse_rad","direct_rad","global_rad"');
return ["success" => false, "message" => $translator->trans("Radiation_should_be_type:'clear_sky_rad','diffuse_rad','direct_rad','global_rad'")];
}
// Create a Redis key for the cache
$cacheKey = sprintf('radiation_%s_%s_%s_%s_%s_%s', $startDate, $day, $intervalInHours, $typeOfRadiation, $latitude, $longitude);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%sP%sD:PT%sH/%s:W/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$day,
$intervalInHours,
$typeOfRadiation,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Solar Power data from the API or cache
* @param array $coordinates The coordinates value
* @param string $startDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param string $endDate The start date and time in the format "YYYY-MM-DDTHH:MM:SSZ"
* @param int $intervalInHours The interval value
* @param int $hour The hour value
* @param string $unit The unit value
* @param string $specification would be like this "installed_capacity_<capacity>"
* @return mixed The Geopotential Height data if available, or an error response
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getSolarPower(array $coordinates, string $startDate, string $endDate, int $intervalInHours, string $hour, string $unit, string $specification, $translator)
{
try {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate)) {
return ["success" => false, "message" => $translator->trans("invalid_start_date")];
}
if (empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_end_date")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
if (!is_numeric($intervalInHours)) {
return ["success" => false, "message" => $translator->trans("interval_should_be_numeric")];;
}
if (!is_numeric($hour)) {
return ["success" => false, "message" => $translator->trans("hours_should_be_numeric")];
}
// Create a Redis key for the cache
$cacheKey = sprintf('solar_power_%s_%s_%s_%s_%s_%s_%s', $specification, $startDate, $endDate, $unit, $hour, $latitude, $longitude);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/solar_power_%s:%s/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$specification,
$unit,
$latitude,
$longitude
);
// p_r($url);
// exit;
$client = new Client(['verify' => false]);
// Make an HTTP request to the API
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
// Handle Guzzle HTTP request exceptions and create and return an error response
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
// Handle other exceptions and create and return an error response
return throw new \Exception($e->getMessage());
}
}
/**
* Rainfall
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getRainfall(array $coordinates, string $startDate, string $endDate, string $duration = '24', $translator, string $format = "json")
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('rainfall_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sM/is_rain_%smin:idx/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$duration,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Dew Point
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getDewPoint(array $coordinates, string $startDate, string $endDate, string $duration = '24', $translator, string $format = "json")
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('dew_point_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/dew_point_2m:C/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Wms
*
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getWms($params)
{
try {
// If cache is empty, get the data from the API
$url = sprintf(
'%s/wms?%s&use_decluttered=true',
$this->apiBaseUrl,
$params['param']
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
return $response->getBody();
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Compute Web Mercator bbox for a tile (z/x/y) and fetch WMS tile.
*/
public function getWmsTileByXYZ(
string $layers,
string $time,
int $z,
int $x,
int $y,
string $format = 'image/webp',
?string $model = null,
string $version = '1.3.0',
string $crs = 'EPSG:3857',
int $width = 256,
int $height = 256,
string $transparent = 'true',
string $styles = ''
) {
// Web Mercator constants
$earthRadius = 6378137;
$circumference = 2 * pi() * $earthRadius;
$resolution = ($circumference / 256) / pow(2, $z);
$minX = ($x * 256) * $resolution - $circumference / 2.0;
$minY = ($y * 256) * $resolution - $circumference / 2.0;
$maxX = (($x + 1) * 256) * $resolution - $circumference / 2.0;
$maxY = (($y + 1) * 256) * $resolution - $circumference / 2.0;
$bbox = $minX . ',' . $minY . ',' . $maxX . ',' . $maxY;
$queryParams = [
'service' => 'WMS',
'request' => 'GetMap',
'layers' => $layers,
'styles' => $styles,
'format' => $format,
'transparent' => $transparent,
'version' => $version,
'time' => $time,
'width' => $width,
'height' => $height,
'crs' => $crs,
'bbox' => $bbox,
];
if (!empty($model)) {
$queryParams['model'] = $model;
}
$paramString = http_build_query($queryParams, '', '&', PHP_QUERY_RFC3986);
return $this->getWms(['param' => $paramString]);
}
/**
* Wind
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $startDate The start date for the forecast
* @param string $endDate The end date for the forecast
* @param string $duration The duration for the forecast (default: '24')
* @param string $intervalType type of interval (default: 'hour')
* @param string $format The format of the forecast data (default: 'json')
* @return array The model forecast data
* @throws \InvalidArgumentException If any of the parameters are invalid or missing
*/
public function getWind(array $coordinates, string $startDate, string $endDate, string $duration = '24', $translator, string $format = "json")
{
try {
// Validate the input parameters
if (empty($coordinates)) {
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
if (!is_array($coordinates) || count($coordinates) < 1) {
return ["success" => false, "message" => $translator->trans("coordinates_should_be_a_non_empty_array")];
}
$latitude = $coordinates[0][0] ?? null;
$longitude = $coordinates[0][1] ?? null;
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
if (!is_numeric($duration)) {
return ["success" => false, "message" => $translator->trans("duration_should_be_numeric")];
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('wind_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate) . $duration));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$url = sprintf(
'%s/%s--%s:PT%sH/wind_speed_u_10m:ms,wind_speed_v_10m:ms/%s,%s/json?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$latitude,
$longitude
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Wind by location
*
* @param string $time The type of data time (e.g., '2023-09-01')
* @param string $location The latitude and longitude of location
* @param string $format return type of json
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getWindByLocation(
string $time,
string $location,
string $format = 'json'
) {
if (!is_string($time)) {
throw new \InvalidArgumentException('Invalid data type for $time. Expected string.');
}
if (!is_string($location)) {
throw new \InvalidArgumentException('Invalid data type for $location. Expected string.');
}
if (!is_string($format)) {
throw new \InvalidArgumentException('Invalid data type for $format. Expected string.');
}
$cacheKey = sprintf('wind_location_%s_%s', $time, $location);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
try {
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s/wind_speed_u_10m:ms,wind_speed_v_10m:ms/%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$time,
$location,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Water Temperature
*
* @param string $query The type of data request (e.g., 't_sea_sfc:ms')
* @param string $format return type of json
* @param string $date The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location in array
* @param string $dimensions type of data (e.g., '500x300')
* @param string $modal type of data (e.g., 'noaa-hycom', 'ecmwf-cmems', 'noaa-hycom')
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getWaterTempereture(
string $query,
array $coordinates,
string $dimensions,
string $format,
string $date,
string $modal
) {
try {
if (empty($query)) {
throw new \InvalidArgumentException('Invalid query');
}
if (empty($date)) {
throw new \InvalidArgumentException('Invalid date');
}
$date = date('Y-m-d\TH:i:s\Z', (strtotime($date)));
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$cacheKey = \App\Lib\Utility::generateKey($query, $coordinates, $dimensions, $date, $format, $modal);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s/%s/%s:%s/%s?%s&use_decluttered=true',
$this->apiBaseUrl,
$date,
$query,
$coordinateString,
$dimensions,
$format,
$modal
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
if ($format == "json") {
$data = json_decode($response->getBody(), true);
} else {
$data = $response->getBody();
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Ocean Current
*
* @param string $query The type of data request (e.g., 'ocean_current_speed_2m:ms')
* @param string $format return type of json
* @param string $date The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location in array
* @param string $dimensions type of data (e.g., '500x300')
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getOceanCurrent(
string $query,
array $coordinates,
string $dimensions,
string $format,
string $date
) {
try {
if (empty($query)) {
throw new \InvalidArgumentException('Invalid query');
}
if (empty($date)) {
throw new \InvalidArgumentException('Invalid dates');
}
$date = date('Y-m-d\TH:i:s\Z', (strtotime($date)));
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$cacheKey = \App\Lib\Utility::generateKey($query, $coordinates, $dimensions, $date, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s/%s/%s:%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$date,
$query,
$coordinateString,
$dimensions,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
if ($format == "json") {
$data = json_decode($response->getBody(), true);
} else {
$data = $response->getBody();
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Oceanic Tides
*
* @param string $query The type of data request (e.g., 'tidal_amplitude:cm')
* @param string $format return type of json
* @param string $date The type of data date (e.g., '2023-09-01')
* @param array $latitude The latitude of location
* @param array $longitude The longitude of location
* @param string $dimensions type of data (e.g., '500x300')
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getOceanicTides(
string $query,
string $latitude,
string $longitude,
string $date,
string $format,
string $resolution,
string $model
) {
try {
if (empty($query)) {
throw new \InvalidArgumentException('Invalid query');
}
if (empty($date)) {
throw new \InvalidArgumentException('Invalid dates');
}
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
throw new \InvalidArgumentException('Invalid longitude');
}
$date = date('Y-m-d\TH:i:s\Z', (strtotime($date)));
$cacheKey = \App\Lib\Utility::generateKey($query, $latitude, $longitude, $date, $format, $resolution, $model);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s%s/%s/%s,%s/%s?%s&use_decluttered=true',
$this->apiBaseUrl,
$date,
$resolution,
$query,
$latitude,
$longitude,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
if ($format == "json") {
$data = json_decode($response->getBody(), true);
} else {
$data = $response->getBody();
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Drought Index
*
* @param string $query The type of data request (e.g., 'drought_index:idx/Asia')
* @param string $format return type of json or html_map
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $longitude The longitude of location
* @param string $latitude The latitude of location
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getDroughtIndex(
string $query,
string $latitude,
string $longitude,
string $date,
string $format,
) {
try {
if (empty($query)) {
throw new \InvalidArgumentException('Invalid query');
}
if (empty($date)) {
throw new \InvalidArgumentException('Invalid dates');
}
if (!is_numeric($latitude) || $latitude < -90 || $latitude > 90) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!is_numeric($longitude) || $longitude < -180 || $longitude > 180) {
throw new \InvalidArgumentException('Invalid longitude');
}
$date = date('Y-m-d\TH:i:s\Z', (strtotime($date)));
$cacheKey = \App\Lib\Utility::generateKey($query, $latitude, $longitude, $date, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s/%s:%s,%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$date,
$query,
$latitude,
$longitude,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
if ($format == "json") {
$data = json_decode($response->getBody(), true);
} else {
$data = $response->getBody();
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches the hourly weather forecast data for a given latitude, longitude, and hour
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param string $hourly The hour for which forecast is required in 24-hour format
* @return array The hourly weather forecast data in JSON format
*/
public function getHourlyForecastWithoutSymbols(array $coordinates, string $startDate, string $endDate, int $hour, string $model)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('cn_hourly_forecast_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $model, $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$url1 = sprintf(
'%s/%s--%s:PT%sH/t_2m:C,wind_speed_10m:kmh,wind_dir_mean_100m_2h:d,prob_precip_2h:p,precip_2h:mm/%+%/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$coordinateString,
$coordinateString
);
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = sprintf('cn_hourly_forecast_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), ($startDate . '-' . $endDate) . $model, $hour);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url1 = sprintf(
'%s/%s--%s:PT%sH/t_2m:C,wind_speed_10m:kmh,wind_dir_mean_100m_2h:d,prob_precip_2h:p,precip_2h:mm/%s,%s/json?model=' . $model . '&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$latitude,
$longitude
);
}
$response = $client->request('GET', $url1, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data1 = json_decode($response->getBody(), true);
$this->redisCache->set($cacheKey, $data1);
return $data1;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Fetches the weather forecast data for a given latitude, longitude, and for selected data range
*
* @param array $coordinates An array of coordinates in the format [[lat1, long1], [lat2, long2], ...]
* @param int $days The number of days for which forecast is required
* @return array|null The weather forecast data in JSON format, or null if there was an error
*/
public function getTempratureByParamsHourly(
array $coordinates,
// Set the data to Re
string $startDate,
string $endDate,
string $parametersStr,
int $hour = 2,
string $model,
$timezone
) {
try {
// Convert start and end dates to the specified timezone
$startDateObj = new \DateTime($startDate, $timezone);
$endDateObj = new \DateTime($endDate, $timezone);
// Format dates to ISO 8601 format for the API request
$startDate = $startDateObj->format('Y-m-d\TH:i:s.v\Z');
$endDate = $endDateObj->format('Y-m-d\TH:i:s.v\Z');
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
// Create a Redis key for the cache
$cacheKey = sprintf('hourly_custom_noti_%s_%s_%s_%s', md5(implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates))), ($startDate . '-' . $endDate), $parametersStr, $model);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
return $cachedData;
}
// Build the API URL
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s+%s/json?source=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$parametersStr,
$coordinateString,
$coordinateString,
$model
);
} else {
// Handle single coordinate case
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
if (empty($latitude) || empty($longitude)) {
throw new \InvalidArgumentException('Invalid coordinates');
}
// Create a Redis key for the cache
$cacheKey = sprintf('hourly_custom_noti_%s_%s_%s_%s', md5(implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates))), ($startDate . '-' . $endDate), $parametersStr, $model);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
return $cachedData;
}
// Build the API URL for a single coordinate
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s,%s/json?source=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$parametersStr,
$latitude,
$longitude,
$model
);
}
// Make the API request
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$data = json_decode($response->getBody(), true);
// Cache the data in Redis
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (GuzzleHttp\Exception\RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
/**
* Tidal Amplitude
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $unit The type of data request unit (e.g., 'cm')
* @param string $format return type of json
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location
* @param string $model type of data Api return (e.g., 'mm-tides')
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getTidalAmplitudes(int $hour, $startDate, $endDate, array $coordinates, $unit, $model, $format)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $coordinates, $unit, $model, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/tidal_amplitude:%s/%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$coordinateString,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $unit, $latitude, $longitude, $model, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/tidal_amplitude:%s/%s,%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$latitude,
$longitude,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* High and Low Tide Times
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $format return type of json
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location
* @param string $model type of data Api return (e.g., 'mm-tides')
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getHighLowTideTimes(int $hour, $startDate, $endDate, array $coordinates, $model, $format)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $coordinates, $model, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/first_high_tide:sql,second_high_tide:sql,first_low_tide:sql,second_low_tide:sql/%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$coordinateString,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $latitude, $longitude, $model, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/first_high_tide:sql,second_high_tide:sql,first_low_tide:sql,second_low_tide:sql/%s,%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$latitude,
$longitude,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Significant Wave Height
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $format return type of json
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getSignificantWaveHeight(int $hour, $startDate, $endDate, array $coordinates, $format)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $coordinate, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/significant_height_wind_waves:m/%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$coordinateString,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $latitude, $longitude, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/significant_height_wind_waves:m/%s,%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$latitude,
$longitude,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Surge Amplitude
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $format return type of json
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param string $unit The type of data unit (e.g., 'cm')
* @param array $coordinates The latitude and longitude of location
* @param string $model type of data Api return (e.g., 'mix')
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getSurgeAmplitude(int $hour, $startDate, $endDate, array $coordinates, $unit, $model, $format)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $coordinate, $unit, $model, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/surge_amplitude:%s/%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$coordinateString,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $latitude, $longitude, $unit, $model, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/surge_amplitude:%s/%s,%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$latitude,
$longitude,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Heat index
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $format return type of json
* @param string $unit request unit type (e.g, 'C')
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location
* @param string $model type of data Api return (e.g., 'mix')
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getHeatIndex(int $hour, $startDate, $endDate, array $coordinates, $unit, $format, $model)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $coordinate, $model, $unit, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/heat_index:%s,t_2m:%s/%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$unit,
$coordinateString,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
// Create a Redis key for the cache
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $latitude, $longitude, $unit, $model, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/heat_index:%s,t_2m:%s/%s,%s/%s?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$unit,
$latitude,
$longitude,
$format,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Atmospheric Density
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $format return type of json
* @param string $level The type of level request (e.g., '2m')
* @param string $unit The type of unit request (e.g., 'kgm3')
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getAirdensity(int $hour, $startDate, $endDate, array $coordinates, $level, $unit, $format)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $coordinates, $level, $unit, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/air_density_%s:%s/%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$level,
$unit,
$coordinateString,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $latitude, $longitude, $level, $unit, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/air_density_%s:%s/%s,%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$level,
$unit,
$latitude,
$longitude,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Soil Moisture Index
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $format return type of json
* @param string $level The type of level request (e.g., '2m')
* @param string $unit The type of unit request (e.g., 'kgm3')
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param array $coordinates The latitude and longitude of location
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getSoilMoistureIndex(int $hour, $startDate, $endDate, array $coordinates, $level, $unit, $format)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $coordinates, $level, $unit, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/soil_moisture_index_%s:%s/%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$level,
$unit,
$coordinateString,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $latitude, $longitude, $level, $unit, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/soil_moisture_index_%s:%s/%s,%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$level,
$unit,
$latitude,
$longitude,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
/**
* Frost & Thaw Depth
*
* @param string $hourly The hour for which forecast is required in 24-hour format
* @param string $format return type of json
* @param string $startDate The type of data date (e.g., '2023-09-01')
* @param string $endDate The type of data date (e.g., '2023-09-01')
* @param string $unit The type of data request (e.g., 'cm')
* @param array $coordinates The latitude and longitude of location
* @throws \InvalidArgumentException If any parameter has an invalid data type
*/
public function getFrostThawAndDepth(int $hour, $startDate, $endDate, $unit, array $coordinates, $format)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
throw new \InvalidArgumentException('Invalid coordinates');
}
}
if (empty($startDate) || empty($endDate)) {
throw new \InvalidArgumentException('Invalid dates');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $unit, $coordinates, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/frost_depth:%s,thaw_depth:%s/%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$unit,
$coordinateString,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
throw new \InvalidArgumentException('Invalid latitude');
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
throw new \InvalidArgumentException('Invalid longitude');
}
if (empty($startDate)) {
throw new \InvalidArgumentException('Invalid startDate');
}
if (empty($endDate)) {
throw new \InvalidArgumentException('Invalid endDate');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
$cacheKey = \App\Lib\Utility::generateKey($hour, $startDate, $endDate, $unit, $latitude, $longitude, $format);
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$url = sprintf(
'%s/%s--%s:PT%sH/frost_depth:%s,thaw_depth:%s/%s,%s/%s?use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hour,
$unit,
$unit,
$latitude,
$longitude,
$format
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
}
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
public function getReportForecastData(array $coordinates, string $startDate, string $endDate, int $hours, string $model = "ksancm-wrf-48", array $parameters = [], $translator, array $cities, $params)
{
try {
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
}
}else{
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
// throw new \InvalidArgumentException('Invalid dates');
}
if ($hours < 1 and $hours > 24) {
throw new \InvalidArgumentException('Invalid hour');
}
$startDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($startDate)));
$endDate = date('Y-m-d\TH:i:s.v\Z', (strtotime($endDate)));
if (empty($parameters)) {
$parameters = [
't_2m:C',
't_max_2m_%sh:C',
't_min_2m_%sh:C',
't_apparent_min_%sh:C',
't_apparent_max_%sh:C',
'wind_speed_mean_10m_%sh:kmh',
'wind_dir_mean_10m_%sh:d',
'prob_precip_%sh:p',
'precip_%sh:mm',
'relative_humidity_mean_2m_%sh:p',
'effective_cloud_cover_mean_%sh:octas',
'dew_point_mean_2m_%sh:C',
'wind_gusts_10m_%sh:kmh',
'visibility:km',
];
}
// Create a Redis key for the cache
$cacheKey = sprintf('daily_forecast_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $model, implode('_', $parameters));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
$timeResolutions = [
'_24h' => '+1 day',
'_12h' => '+12 hours',
'_6h' => '+6 hours',
'_3h' => '+3 hours',
'_1h' => '+1 hour'
];
$adjustedParameters = [];
$nonAdjustedParameters = [];
foreach ($parameters as $parameter) {
$matched = false;
foreach ($timeResolutions as $key => $adjustment) {
if (strpos($parameter, $key) !== false) {
$matched = true;
$adjustedParameters[$adjustment][] = $parameter;
break;
}
}
if (!$matched) {
$nonAdjustedParameters[] = $parameter;
}
}
// Construct the URL
// $url = "{$this->apiBaseUrl}/{$startDate}--{$endDate}:{$duration}/t_2m:C,wind_speed_10m:kmh,wind_dir_10m:d,sfs_pressure:hPa,precip_10min:mm,relative_humidity_2m:p,visibility:km,dew_point_2m:c,wind_gusts_10m_1h:kmh,ceiling_height_agl:m,geopotential_height:m,t_min_2m_24h:C,t_max_2m_24h:C,precip_24h:mm,total_cloud_cover:octas/metar_{$metar}/json?source=mix-obs&on_invalid=fill_with_invalid";
$dataFinal = [
'data' => []
];
foreach ($adjustedParameters as $adjustment => $adjParams) {
$adjustedStartDate = (new \DateTime($startDate))->modify($adjustment)->format('Y-m-d\TH:i:s.v\Z');
$adjustedEndDate = (new \DateTime($endDate))->modify($adjustment)->format('Y-m-d\TH:i:s.v\Z');
$data = $this->fetchReportForecastData($coordinates,$adjustedStartDate,$adjustedEndDate,$hours, $model,$adjParams,$translator,$cities, $params);
// Revert dates to original range
if (isset($data['data']) && is_array($data['data'])) {
foreach ($data['data'] as &$datum) {
if (isset($datum['coordinates']) && is_array($datum['coordinates'])) {
foreach ($datum['coordinates'] as &$coordinate) {
if (isset($coordinate['dates']) && is_array($coordinate['dates'])) {
foreach ($coordinate['dates'] as &$date) {
if (isset($date['date'])) {
// Convert the date back by subtracting the adjustment
$adjustmentValue = str_replace(['+', ' '], '', $adjustment); // Remove '+' and extra spaces
$date['date'] = (new \DateTime($date['date']))
->modify('-' . $adjustmentValue)
->format('Y-m-d\TH:i:s\Z');
}
}
}
}
}
}
} else {
$data['data'] = []; // Ensure 'data' exists
}
// Merge into $dataFinal
if (empty($dataFinal['version'])) {
$dataFinal['version'] = $data['version'] ?? null;
$dataFinal['user'] = $data['user'] ?? null;
$dataFinal['dateGenerated'] = $data['dateGenerated'] ?? null;
$dataFinal['status'] = $data['status'] ?? null;
}
if (isset($data['data']) && is_array($data['data'])) {
$dataFinal['data'] = array_merge($dataFinal['data'], $data['data']);
}
}
// Process non-adjusted parameters
if (!empty($nonAdjustedParameters)) {
$data= $this->fetchReportForecastData($coordinates,$startDate,$endDate,$hours, $model ,$nonAdjustedParameters,$translator,$cities, $params);
if (isset($data['data']) && is_array($data['data'])) {
$dataFinal['data'] = array_merge($dataFinal['data'], $data['data']);
}
}
// Reorder data based on parameters
$dataFinal['data'] = isset($dataFinal['data']) && is_array($dataFinal['data'])
? $this->orderResults($dataFinal['data'], $parameters)
: [];
$result = [];
foreach ($dataFinal['data'] as $param) {
foreach ($param['coordinates'] as $paramCoordinates) {
// exit;
$paramCoordinates['lat'] = number_format($paramCoordinates['lat'], 6, '.', '');
$paramCoordinates['lon'] = number_format($paramCoordinates['lon'], 6, '.', '');
$cityKey = $paramCoordinates['lat'] . '|' . $paramCoordinates['lon'];
if (!isset($result[$cityKey])) {
$result[$cityKey] = [];
if (isset($cities[$cityKey]['en'])) {
$result[$cityKey] = [
'cityEn' => $cities[$cityKey]['en'],
'cityAr' => $cities[$cityKey]['ar'],
'lat' => $paramCoordinates['lat'],
'lon' => $paramCoordinates['lon'],
'parameters' => [],
];
} else {
$result[$cityKey] = [
'city' => $cities[$cityKey],
'lat' => $paramCoordinates['lat'],
'lon' => $paramCoordinates['lon'],
'parameters' => [],
];
}
}
$parameterData = [
'parameter' => $param['parameter'],
'dates' => [],
];
foreach ($paramCoordinates['dates'] as $item) {
$parameterData['dates'][] = [
'date' => $item['date'], // You can modify this as needed
'value' => $item['value'], // You can modify this as needed
];
}
// p_r($parameterData);
$result[$cityKey]['parameters'][] = $parameterData;
}
}
$result = array_values($result);
if (isset($params['report_type_id']) && !empty($params['report_type_id'])) {
$latestReport = new Report\Listing();
$latestReport->setCondition('reportType__id = ?', [$params['report_type_id']]);
$latestReport->setOrderKey("o_creationDate");
$latestReport->setOrder("desc");
$latestReport = $latestReport->current();
if ($latestReport) {
$jsonData = json_decode($latestReport->getJsonData(), true);
foreach ($result as &$value) {
// Compare latitude and longitude
foreach ($jsonData as $jsonEntry) {
if ($value['lat'] == $jsonEntry['lat'] && $value['lon'] == $jsonEntry['lon']) {
// Latitude and longitude match, proceed with parameter comparison
foreach ($value['parameters'] as &$paramValue) {
foreach ($jsonEntry['parameters'] as $jsonParam) {
if ($jsonParam['parameter'] == $paramValue['parameter']) {
// Parameter matches, check dates now
foreach ($paramValue['dates'] as &$dateValue) {
foreach ($jsonParam['dates'] as $jsonDate) {
if ($dateValue['date'] == $jsonDate['date']) {
// Exact match found, override the value
$dateValue['value'] = $jsonDate['value'];
// Continue checking all dates, no break here
}
}
}
unset($dateValue); // Ensure reference is not carried over
}
}
}
unset($paramValue); // Ensure reference is not carried over
}
}
}
unset($value); // Ensure reference is not carried over
}
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $dataFinal);
return $result;
} catch (GuzzleHttp\Exception\RequestException $e) {
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
public function fetchReportForecastData($coordinates,$startDate,$endDate,$hours, $model,$parameters,$translator,$cities, $params){
$dataFinal = [];
$client = new Client(['verify' => false]);
if (count($coordinates) > 1) {
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
}else{
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
}
while (!empty($parameters)) {
$batchParameters = array_splice($parameters, 0, 10); // Take up to 10 parameters
$batchQueryString = implode(',', $batchParameters);
$batchQueryString = str_replace('%s', $hours, $batchQueryString);
if (count($coordinates) > 1) {
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s/json?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hours,
$batchQueryString,
$coordinateString,
$model
);
}else{
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s,%s/json?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hours,
$batchQueryString,
$latitude,
$longitude,
$model
);
}
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
// Merge data from the current API call into the final data
$dataFinal['data'] = array_merge($dataFinal['data'] ?? [], $data['data']);
}
foreach ($coordinates as $coOrd) {
$weatherSymbols = $this->getWeatherSymbols([$coOrd], $startDate, $endDate, 'PT' . $hours . 'H', $hours . 'h', true);
if (isset($weatherSymbols['data'][0]['parameter'])) {
$dataFinal['symbols'][$coOrd[0] . '|' . $coOrd[1]] = $weatherSymbols['data'][0];
}
}
// p_r($dataFinal);
// exit;
// Convert the associative array to indexed array
return $dataFinal;
}
public function getAdminReportForecastData(array $coordinates, string $startDate, string $endDate, string $model = "ksancm-wrf-48", array $parameters12h = [], array $parameters24h = [], $translator, array $cities, $params)
{
try {
if (isset($params['report_type_id']) && !empty($params['report_type_id'])) {
$latestReport = new Report\Listing();
$reportType = \Pimcore\Model\DataObject::getById($params['report_type_id']);
$latestReport->filterByReportType($reportType);
$latestReport->setOrderKey("createdOn");
$latestReport->setLimit(1);
$latestReport->setOrder("desc");
$latestReport = $latestReport->current();
}
if (count($coordinates) > 1) {
// Validate the input parameters
foreach ($coordinates as $coordinate) {
if (count($coordinate) < 2 || !is_numeric($coordinate[0]) || !is_numeric($coordinate[1])) {
// throw new \InvalidArgumentException('Invalid coordinates');
return ["success" => false, "message" => $translator->trans("invalid_coordinates")];
}
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
// throw new \InvalidArgumentException('Invalid dates');
}
// Create a Redis key for the cache
$cacheKey = sprintf('daily_forecast_%s_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $model, implode('_', $parameters12h), implode('_', $parameters24h));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
// return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$dataFinal = [];
// Function to perform the API requests for given parameters and hours
$performApiRequests = function ($parameters, $hours, $startDate, $endDate) use ($client, $coordinateString, $model) {
$data = [];
while (!empty($parameters)) {
$batchParameters = array_splice($parameters, 0, 10); // Take up to 10 parameters
$batchQueryString = implode(',', $batchParameters);
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s/json?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hours,
$batchQueryString,
$coordinateString,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$dataBatch = json_decode($response->getBody(), true);
// Merge data from the current API call into the data array
$data['data'] = array_merge($data['data'] ?? [], $dataBatch['data']);
}
return $data;
};
// Process 24h parameters
if (!empty($parameters24h)) {
$startDateUpdated = new DateTime($startDate);
$endDateUpdated = new DateTime($endDate);
$startDateUpdated = $startDateUpdated->modify('+1 day')->format('Y-m-d\TH:i:s\Z');
$endDateUpdated = $endDateUpdated->modify('+1 day')->format('Y-m-d\TH:i:s\Z');
$data24h = $performApiRequests($parameters24h, 24, $startDateUpdated, $endDateUpdated);
if (!empty($data24h)) {
foreach ($data24h['data'] as &$datum) {
if (isset($datum['coordinates'])) {
foreach ($datum['coordinates'] as &$coordinate) {
foreach ($coordinate['dates'] as &$date) {
$dateObj = new DateTime($date['date']);
$date['date'] = $dateObj->modify('-1 day')->format('Y-m-d\TH:i:s\Z');
}
}
}
}
// Correctly append 24h data to $datainal
if (!empty($data24h['data'])) {
// Existing code to adjust dates in $data24h['data']
if (empty($dataFinal['data'])) {
$dataFinal['data'] = $data24h['data'];
} else {
$dataFinal['data'] = array_merge($dataFinal['data'], $data24h['data']);
}
}
}
}
// Process 12h parameters
if (!empty($parameters12h)) {
$startDateUpdated = new DateTime($startDate);
$endDateUpdated = new DateTime($endDate);
$startDateUpdated = $startDateUpdated->modify('+12 hours')->format('Y-m-d\TH:i:s\Z');
$endDateUpdated = $endDateUpdated->modify('+12 hours')->format('Y-m-d\TH:i:s\Z');
$data12h = $performApiRequests($parameters12h, 12, $startDateUpdated, $endDateUpdated);
if (!empty($data12h)) {
foreach ($data12h['data'] as &$datum) {
if (isset($datum['coordinates'])) {
foreach ($datum['coordinates'] as &$coordinate) {
foreach ($coordinate['dates'] as &$date) {
$dateObj = new DateTime($date['date']);
$date['date'] = $dateObj->modify('-12 hours')->format('Y-m-d\TH:i:s\Z');
}
}
}
}
// Correctly append 12h data to $dataFinal
if (!empty($data12h['data'])) {
// Existing code to adjust dates in $data12h['data']
if (empty($dataFinal['data'])) {
$dataFinal['data'] = $data12h['data'];
} else {
$dataFinal['data'] = array_merge($dataFinal['data'], $data12h['data']);
}
}
}
}
foreach ($coordinates as $coOrd) {
$weatherSymbols = $this->getWeatherSymbols([$coOrd], $startDate, $endDate, 'PT12H', '12h');
if (isset($weatherSymbols['data'][0]['parameter'])) {
$dataFinal['symbols'][$coOrd[0] . '|' . $coOrd[1]] = $weatherSymbols['data'][0];
}
}
$result = [];
foreach ($dataFinal['data'] as $param) {
foreach ($param['coordinates'] as $paramCoordinates) {
$paramCoordinates['lat'] = number_format($paramCoordinates['lat'], 6, '.', '');
$paramCoordinates['lon'] = number_format($paramCoordinates['lon'], 6, '.', '');
$cityKey = $paramCoordinates['lat'] . '|' . $paramCoordinates['lon'];
if (!isset($result[$cityKey])) {
$result[$cityKey] = [];
if (isset($cities[$cityKey]['en'])) {
if (isset($paramCoordinates['lat']) && isset($paramCoordinates['lon'])) {
$result[$cityKey] = [
'cityEn' => $cities[$cityKey]['en'],
'cityAr' => $cities[$cityKey]['ar'],
'lat' => $paramCoordinates['lat'],
'lon' => $paramCoordinates['lon'],
'parameters' => [],
];
}
} else {
if (isset($paramCoordinates['lat']) && isset($paramCoordinates['lon'])) {
$result[$cityKey] = [
'city' => $cities[$cityKey],
'lat' => $paramCoordinates['lat'],
'lon' => $paramCoordinates['lon'],
'parameters' => [],
];
}
}
}
$parameterData = [
'parameter' => $param['parameter'],
'dates' => [],
];
foreach ($paramCoordinates['dates'] as $date) {
$parameterData['dates'][] = [
'date' => $date['date'], // You can modify this as needed
'value' => $date['value'], // You can modify this as needed
];
}
$result[$cityKey]['parameters'][] = $parameterData;
}
}
// Convert the associative array to indexed array
$result = array_values($result);
if (isset($params['report_type_id']) && !empty($params['report_type_id'])) {
// $latestReport = new Report\Listing();
// $reportType = \Pimcore\Model\DataObject::getById($params['report_type_id']);
// $latestReport->filterByReportType($reportType);
// $latestReport->setOrderKey("createdOn");
// $latestReport->setOrder("desc");
// $latestReport = $latestReport->current();
if ($latestReport) {
$jsonData = json_decode($latestReport->getJsonData(), true);
foreach ($result as &$value) {
// Compare latitude and longitude
foreach ($jsonData as $jsonEntry) {
if (isset($value['lat']) && isset($jsonEntry['lat']) && ($value['lat'] == $jsonEntry['lat']) && isset($value['lon']) && isset($jsonEntry['lon']) && ($value['lon'] == $jsonEntry['lon'])) {
// Latitude and longitude match, proceed with parameter comparison
foreach ($value['parameters'] as &$paramValue) {
foreach ($jsonEntry['parameters'] as $jsonParam) {
if ($jsonParam['parameter'] == $paramValue['parameter']) {
// Parameter matches, check dates now
foreach ($paramValue['dates'] as &$dateValue) {
foreach ($jsonParam['dates'] as $jsonDate) {
if ($dateValue['date'] == $jsonDate['date']) {
// Exact match found, override the value
$dateValue['value'] = $jsonDate['value'];
// Continue checking all dates, no break here
}
}
}
unset($dateValue); // Ensure reference is not carried over
}
}
}
unset($paramValue); // Ensure reference is not carried over
}
}
}
unset($value); // Ensure reference is not carried over
}
}
} else {
if ($coordinates) {
$latitude = $coordinates[0][0];
$longitude = $coordinates[0][1];
}
// Validate the input parameters
if (!preg_match('/^[-]?[0-9]{1,2}\.[0-9]+/', $latitude)) {
// throw new \InvalidArgumentException('Invalid latitude');
return ["success" => false, "message" => $translator->trans("invalid_latitude")];
}
if (!preg_match('/^[-]?[0-9]{1,3}\.[0-9]+/', $longitude)) {
// throw new \InvalidArgumentException('Invalid longitude');
return ["success" => false, "message" => $translator->trans("invalid_longitude")];
}
if (empty($startDate) || empty($endDate)) {
return ["success" => false, "message" => $translator->trans("invalid_dates")];
}
// Create a Redis key for the cache
$cacheKey = sprintf('daily_forecast_%s_%s_%s_%s', implode('_', array_map(function ($coordinate) {
return implode('_', $coordinate);
}, $coordinates)), (($startDate) . '-' . ($endDate)) . $model, implode('_', $parameters12h), implode('_', $parameters24h));
// Try to get the data from Redis cache
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// If cache is empty, get the data from the API
$client = new Client(['verify' => false]);
$coordinateString = implode('+', array_map(fn($coords) => implode(',', $coords), $coordinates));
$dataFinal = [];
// Function to perform the API requests for given parameters and hours
$performApiRequests = function ($parameters, $hours, $startDate, $endDate) use ($client, $latitude, $longitude, $model) {
$data = [];
while (!empty($parameters)) {
$batchParameters = array_splice($parameters, 0, 10); // Take up to 10 parameters
$batchQueryString = implode(',', $batchParameters);
$url = sprintf(
'%s/%s--%s:PT%sH/%s/%s,%s/json?model=%s&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$hours,
$batchQueryString,
$latitude,
$longitude,
$model
);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
'timeout' => 600
]);
$statusCode = $response->getStatusCode();
$dataBatch = json_decode($response->getBody(), true);
// Merge data from the current API call into the data array
$data['data'] = array_merge($data['data'] ?? [], $dataBatch['data']);
}
return $data;
};
// Process 24h parameters
if (!empty($parameters24h)) {
$startDateUpdated = new DateTime($startDate);
$endDateUpdated = new DateTime($endDate);
$startDateUpdated = $startDateUpdated->modify('+1 day')->format('Y-m-d\TH:i:s\Z');
$endDateUpdated = $endDateUpdated->modify('+1 day')->format('Y-m-d\TH:i:s\Z');
$data24h = $performApiRequests($parameters24h, 24, $startDateUpdated, $endDateUpdated);
if (!empty($data24h)) {
foreach ($data24h['data'] as &$datum) {
if (isset($datum['coordinates'])) {
foreach ($datum['coordinates'] as &$coordinate) {
foreach ($coordinate['dates'] as &$date) {
$dateObj = new DateTime($date['date']);
$date['date'] = $dateObj->modify('-1 day')->format('Y-m-d\TH:i:s\Z');
}
}
}
}
// Correctly append 24h data to $datainal
if (!empty($data24h['data'])) {
// Existing code to adjust dates in $data24h['data']
if (empty($dataFinal['data'])) {
$dataFinal['data'] = $data24h['data'];
} else {
$dataFinal['data'] = array_merge($dataFinal['data'], $data24h['data']);
}
}
}
}
// Process 12h parameters
if (!empty($parameters12h)) {
$startDateUpdated = new DateTime($startDate);
$endDateUpdated = new DateTime($endDate);
$startDateUpdated = $startDateUpdated->modify('+12 hours')->format('Y-m-d\TH:i:s\Z');
$endDateUpdated = $endDateUpdated->modify('+12 hours')->format('Y-m-d\TH:i:s\Z');
$data12h = $performApiRequests($parameters12h, 12, $startDateUpdated, $endDateUpdated);
if (!empty($data12h)) {
foreach ($data12h['data'] as &$datum) {
if (isset($datum['coordinates'])) {
foreach ($datum['coordinates'] as &$coordinate) {
foreach ($coordinate['dates'] as &$date) {
$dateObj = new DateTime($date['date']);
$date['date'] = $dateObj->modify('-12 hours')->format('Y-m-d\TH:i:s\Z');
}
}
}
}
// Correctly append 12h data to $dataFinal
if (!empty($data12h['data'])) {
// Existing code to adjust dates in $data12h['data']
if (empty($dataFinal['data'])) {
$dataFinal['data'] = $data12h['data'];
} else {
$dataFinal['data'] = array_merge($dataFinal['data'], $data12h['data']);
}
}
}
}
foreach ($coordinates as $coOrd) {
$weatherSymbols = $this->getWeatherSymbols([$coOrd], $startDate, $endDate, 'PT12H', '12h');
if (isset($weatherSymbols['data'][0]['parameter'])) {
$dataFinal['symbols'][$coOrd[0] . '|' . $coOrd[1]] = $weatherSymbols['data'][0];
}
}
$result = [];
foreach ($dataFinal['data'] as $param) {
foreach ($param['coordinates'] as $paramCoordinates) {
$paramCoordinates['lat'] = number_format($paramCoordinates['lat'], 6, '.', '');
$paramCoordinates['lon'] = number_format($paramCoordinates['lon'], 6, '.', '');
$cityKey = $paramCoordinates['lat'] . '|' . $paramCoordinates['lon'];
if (!isset($result[$cityKey])) {
$result[$cityKey] = [];
if (isset($cities[$cityKey]['en'])) {
$result[$cityKey] = [
'cityEn' => $cities[$cityKey]['en'],
'cityAr' => $cities[$cityKey]['ar'],
'lat' => $paramCoordinates['lat'],
'lon' => $paramCoordinates['lon'],
'parameters' => [],
];
} else {
$result[$cityKey] = [
'city' => $cities[$cityKey],
'lat' => $paramCoordinates['lat'],
'lon' => $paramCoordinates['lon'],
'parameters' => [],
];
}
}
$parameterData = [
'parameter' => $param['parameter'],
'dates' => [],
];
foreach ($paramCoordinates['dates'] as $date) {
$parameterData['dates'][] = [
'date' => $date['date'], // You can modify this as needed
'value' => $date['value'], // You can modify this as needed
];
}
$result[$cityKey]['parameters'][] = $parameterData;
}
}
// Convert the associative array to indexed array
$result = array_values($result);
if (isset($params['report_type_id']) && !empty($params['report_type_id'])) {
// $latestReport = new Report\Listing();
// $reportType = \Pimcore\Model\DataObject::getById($params['report_type_id']);
// $latestReport->filterByReportType($reportType);
// $latestReport->setOrderKey("createdOn");
// $latestReport->setOrder("desc");
// $latestReport = $latestReport->current();
if ($latestReport) {
$jsonData = json_decode($latestReport->getJsonData(), true);
foreach ($result as &$value) {
// Compare latitude and longitude
foreach ($jsonData as $jsonEntry) {
if ($value['lat'] == $jsonEntry['lat'] && $value['lon'] == $jsonEntry['lon']) {
// Latitude and longitude match, proceed with parameter comparison
foreach ($value['parameters'] as &$paramValue) {
foreach ($jsonEntry['parameters'] as $jsonParam) {
if ($jsonParam['parameter'] == $paramValue['parameter']) {
// Parameter matches, check dates now
foreach ($paramValue['dates'] as &$dateValue) {
foreach ($jsonParam['dates'] as $jsonDate) {
if ($dateValue['date'] == $jsonDate['date']) {
// Exact match found, override the value
$dateValue['value'] = $jsonDate['value'];
// Continue checking all dates, no break here
}
}
}
unset($dateValue); // Ensure reference is not carried over
}
}
}
unset($paramValue); // Ensure reference is not carried over
}
}
}
unset($value); // Ensure reference is not carried over
}
}
}
// Set the data to Redis cache
// $this->redisCache->set($cacheKey, $dataFinal);
return $result;
} catch (GuzzleHttp\Exception\RequestException $e) {
// p_r($e->getMessage());
return throw new \Exception($e->getMessage());
} catch (\Exception $e) {
return throw new \Exception($e->getMessage());
}
}
public function getBarbs(string $windSpeed, string $dateTime, string $resolution, string $accessToken): array
{
try {
$client = new Client(['verify' => false]);
$url = sprintf(
"%s/mvt/barbs/%s/style.json?datetime=%s&resolution=%s&access_token=%s&use_decluttered=true",
$this->apiBaseUrl,
$windSpeed,
$dateTime,
$resolution,
$accessToken
);
$response = $client->request('GET', $url, ['auth' => [$this->username, $this->password]]);
$data = json_decode($response->getBody(), true);
return $data;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
public function getMaskLayerData(string $query): array
{
try {
$client = new Client(['verify' => false]);
$url = sprintf(
"%s/%s",
$this->apiBaseUrl,
$query
);
$response = $client->request('GET', $url, ['auth' => [$this->username, $this->password]]);
$data = json_decode($response->getBody(), true);
return $data;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
public function getIsolines(string $measure, string $dateTime, string $accessToken): array
{
try {
$client = new Client(['verify' => false]);
$url = sprintf(
"%s/mvt/isolines/%s/style.json?datetime=%s&access_token=%s&use_decluttered=true",
$this->apiBaseUrl,
$measure,
$dateTime,
$accessToken
);
$response = $client->request('GET', $url, ['auth' => [$this->username, $this->password]]);
$data = json_decode($response->getBody(), true);
return $data;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
public function getAviationReports(string $meter, string $dateTime, string $accessToken): array
{
try {
$client = new Client(['verify' => false]);
$url = sprintf(
"%s/mvt/aviation_reports/%s/style.json?datetime=%s&access_token=%s&use_decluttered=true",
$this->apiBaseUrl,
$meter,
$dateTime,
$accessToken
);
$response = $client->request('GET', $url, ['auth' => [$this->username, $this->password]]);
$data = json_decode($response->getBody(), true);
return $data;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
public function getOceanCurrentSpeed(string $dateTime, string $bBox): array
{
try {
$client = new Client(['verify' => false]);
$url = sprintf(
"%s/%s/ocean_current_u:ms,ocean_current_v:ms/%s/json?use_decluttered=true",
$this->apiBaseUrl,
$dateTime,
$bBox
);
$response = $client->request('GET', $url, ['auth' => [$this->username, $this->password]]);
$data = json_decode($response->getBody(), true);
return $data;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
public function getWMSMAP(string $legendGraphics, string $format, string $layer, string $style = '')
{
try {
$client = new Client(['verify' => false]);
// Conditionally add the STYLE parameter to the URL if it's provided
$stylePart = $style ? "&STYLE=" . urlencode($style) : '';
$url = sprintf(
"%s/wms?VERSION=1.3.0&REQUEST=%s&FORMAT=%s&LAYER=%s%s&use_decluttered=true",
$this->apiBaseUrl,
$legendGraphics,
$format,
$layer,
$stylePart
);
$response = $client->request('GET', $url, ['auth' => [$this->username, $this->password]]);
// Get the raw body content
$content = $response->getBody()->getContents();
// Set headers and create a response object for the PNG image
$httpResponse = new Response($content, Response::HTTP_OK, [
'Content-Type' => $format
]);
return $httpResponse;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
public function getWeatherStationData(string $typeName, string $parameters, string $dateTime, string $bBox)
{
try {
$dateTimeObj = new \DateTime($dateTime);
$dateTimeObj->sub(new \DateInterval('PT10M'));
$adjustedDateTime = $dateTimeObj->format('Y-m-d\TH:i:s.v\Z');
$client = new Client(['verify' => false]);
$url = sprintf(
"%s/wfs?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=%s&PARAMETERS=%s&TIME=%s&BBOX=%s&use_decluttered=true",
$this->apiBaseUrl,
$typeName,
$parameters,
$adjustedDateTime,
$bBox
);
$response = $client->request('GET', $url, ['auth' => [$this->username, $this->password]]);
// Get the raw body content
$content = $response->getBody()->getContents();
// Set headers and create a response object for the XML File
$httpResponse = new Response($content, Response::HTTP_OK, [
'Content-Type' => 'application/xml'
]);
return $httpResponse;
// return $response->getBody();
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
function getGridLayer($dateTime, $parameter, $coordinates, $resolution, $format, $source, $bbox, $calibrated, $translator)
{
try {
if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/', $dateTime)) {
throw new \InvalidArgumentException($translator->trans('invalid_date_format'));
}
if (!$parameter) {
throw new \InvalidArgumentException($translator->trans('invalid_unit'));
}
if (count($coordinates) < 1 || !is_array($coordinates[0]) || count($coordinates[0]) < 2) {
throw new \InvalidArgumentException($translator->trans('invalid_co_ordinates'));
}
if (!preg_match('/^\d+x\d+$/', $resolution)) {
throw new \InvalidArgumentException($translator->trans('invalid_resolution'));
}
if (!in_array($format, ['json', 'xml', 'csv'])) {
throw new \InvalidArgumentException($translator->trans('invalid_format'));
}
if (!is_string($source)) {
throw new \InvalidArgumentException($translator->trans('invalid_source'));
}
if (count($bbox) !== 4) {
throw new \InvalidArgumentException($translator->trans('invalid_bbox_elements'));
}
if (!in_array($calibrated, ['true', 'false'])) {
throw new \InvalidArgumentException($translator->trans('invalid_calibrated_value'));
}
$dateTime = urlencode($dateTime);
$coordinateString = implode('_', array_map(fn($coords) => implode(',', $coords), $coordinates));
$bboxString = implode(',', $bbox);
$cacheKey = \App\Lib\Utility::generateKey($dateTime, $coordinateString, $bboxString, $parameter);
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null) {
// Return the cached data if available
return $cachedData;
}
// Construct the URL
$url = "{$this->apiBaseUrl}/{$dateTime}/{$parameter}/{$coordinateString}:{$resolution}/{$format}?source={$source}&bbox={$bboxString}&calibrated={$calibrated}&use_decluttered=true";
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $data);
return $data;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
public function getMetarData($startDate, $endDate, $metar, $duration, $translator, $parameter, $genExcel)
{
try {
// if (!preg_match('/^20\d{2}-\d{2}-\d{2}T\d{2}Z$/', $startDate)) {
// throw new \InvalidArgumentException($translator->trans('invalid_date_format'));
// }
// if (!preg_match('/^20\d{2}-\d{2}-\d{2}T\d{2}Z$/', $endDate)) {
// throw new \InvalidArgumentException($translator->trans('invalid_date_format'));
// }
if (!preg_match('/^20\d{2}-\d{2}-\d{2}T\d{2}(:\d{2}(:\d{2}(\.\d{3})?)?)?Z$/', $startDate)) {
throw new \InvalidArgumentException($translator->trans('invalid_date_format'));
}
if (!preg_match('/^20\d{2}-\d{2}-\d{2}T\d{2}(:\d{2}(:\d{2}(\.\d{3})?)?)?Z$/', $endDate)) {
throw new \InvalidArgumentException($translator->trans('invalid_date_format'));
}
$cacheKey = \App\Lib\Utility::generateKey($startDate, $endDate, $metar, $duration, $parameter);
$cachedData = $this->redisCache->get($cacheKey);
if ($cachedData !== null && !$genExcel) {
// Return the cached data if available
return $cachedData;
}
if ($genExcel) {
$parameters[] = $parameter;
} elseif (!empty($parameter) && !$genExcel) {
$parameters = $parameter;
} else {
$parameters = [
't_2m:C',
'wind_speed_10m:kmh',
'wind_dir_10m:d',
'msl_pressure:hPa',
'precip_1h:mm',
'relative_humidity_2m:p',
'visibility:km',
'dew_point_2m:c',
'wind_gusts_10m_1h:kmh',
'ceiling_height_agl:m',
'geopotential_height:m',
't_min_2m_24h:C',
't_max_2m_24h:C',
'precip_24h:mm',
'total_cloud_cover:octas',
'wind_speed_10m:kn',
'wind_gusts_10m_1h:kn',
];
}
$timeResolutions = [
'_24h' => '+1 day',
'_12h' => '+12 hours',
'_6h' => '+6 hours',
'_3h' => '+3 hours',
'_1h' => '+1 hour'
];
$adjustedParameters = [];
$nonAdjustedParameters = [];
foreach ($parameters as $parameter) {
$matched = false;
foreach ($timeResolutions as $key => $adjustment) {
if (strpos($parameter, $key) !== false) {
$matched = true;
$adjustedParameters[$adjustment][] = $parameter;
break;
}
}
if (!$matched) {
$nonAdjustedParameters[] = $parameter;
}
}
// Construct the URL
// $url = "{$this->apiBaseUrl}/{$startDate}--{$endDate}:{$duration}/t_2m:C,wind_speed_10m:kmh,wind_dir_10m:d,sfs_pressure:hPa,precip_10min:mm,relative_humidity_2m:p,visibility:km,dew_point_2m:c,wind_gusts_10m_1h:kmh,ceiling_height_agl:m,geopotential_height:m,t_min_2m_24h:C,t_max_2m_24h:C,precip_24h:mm,total_cloud_cover:octas/metar_{$metar}/json?source=mix-obs&on_invalid=fill_with_invalid";
$dataFinal = [
'version' => null,
'user' => null,
'dateGenerated' => null,
'status' => null,
'data' => []
];
foreach ($adjustedParameters as $adjustment => $params) {
$adjustedStartDate = (new \DateTime($startDate))->format('Y-m-d\TH:i:s.v\Z');
$adjustedEndDate = (new \DateTime($endDate))->format('Y-m-d\TH:i:s.v\Z');
$data = $this->fetchMetarData($adjustedStartDate, $adjustedEndDate, $metar, $duration, $params);
// Revert dates to original range
if (isset($data['data']) && is_array($data['data'])) {
foreach ($data['data'] as &$datum) {
if (isset($datum['coordinates'][0]['dates']) && is_array($datum['coordinates'][0]['dates'])) {
foreach ($datum['coordinates'][0]['dates'] as &$date) {
if (isset($date['date'])) {
$date['date'] = (new \DateTime($date['date']))
->modify('-' . ltrim($adjustment, '+'))
->format('Y-m-d\TH:i:s.v\Z');
}
}
}
}
} else {
$data['data'] = []; // Ensure 'data' exists
}
// Merge into $dataFinal
if (empty($dataFinal['version'])) {
$dataFinal['version'] = $data['version'] ?? null;
$dataFinal['user'] = $data['user'] ?? null;
$dataFinal['dateGenerated'] = $data['dateGenerated'] ?? null;
$dataFinal['status'] = $data['status'] ?? null;
}
if (isset($data['data']) && is_array($data['data'])) {
$dataFinal['data'] = array_merge($dataFinal['data'], $data['data']);
}
}
if (!empty($nonAdjustedParameters)) {
$data = $this->fetchMetarData($startDate, $endDate, $metar, $duration, $nonAdjustedParameters);
if (isset($data['data']) && is_array($data['data'])) {
$dataFinal['version'] = $data['version'] ?? null;
$dataFinal['user'] = $data['user'] ?? null;
$dataFinal['dateGenerated'] = $data['dateGenerated'] ?? null;
$dataFinal['status'] = $data['status'] ?? null;
$dataFinal['data'] = array_merge($dataFinal['data'], $data['data']);
}
}
// Reorder data based on parameters
$dataFinal['data'] = isset($dataFinal['data']) && is_array($dataFinal['data'])
? $this->orderResults($dataFinal['data'], $parameters)
: [];
if (strpos($metar, ',') === false) {
//get station name and alternative id
if (count($dataFinal['data']) > 0) {
$metarData = $this->getWeatherStationDataByHashId($dataFinal['data']);
$dataFinal['data'] = $metarData;
}
}
if ($genExcel) {
$csvData[] = ['Station Name', 'Parameter(c)', 'Last Update'];
if (count($dataFinal['data']) > 0) {
foreach ($dataFinal['data'] as $key => $value) {
foreach ($value as $key1 => $value1) {
if (!is_array($value1)) {
$parameter = $value1;
}
if (is_array($value1)) {
foreach ($value1 as $key2 => $value2) {
$station_hash = $value2['station_id'] ?? null;
$station_name = $value2['station_name'] ?? null;
$station_id = $value2['station_alternativeIds'] ?? null;
if (is_array($value2['dates'])) {
foreach ($value2['dates'] as $key3 => $value3) {
$date = $value3['date'];
$value = $value3['value'];
$csvData[] = [$station_name, $value == '-999' ? 'N/A' : $value, $date];
}
}
}
}
}
}
}
$xlsxReport = \Pimcore\Model\Asset::getByPath("/report/StationCsv/metar_station_weather_data.xlsx");
if ($xlsxReport !== null) {
$xlsxReport->delete();
}
$excelData = ExcelGenerator::createAndSaveXlsx($csvData, "metar_station_weather_data", true, 'StationCsv');
return $excelData;
}
// Set the data to Redis cache
$this->redisCache->set($cacheKey, $dataFinal);
return $dataFinal;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
private function fetchMetarData($startDate, $endDate, $metar, $duration, $parameters)
{
$dataFinal = [];
while (!empty($parameters)) {
$batchParameters = array_splice($parameters, 0, 10); // Take up to 10 parameters
$batchQueryString = implode(',', $batchParameters);
$url = sprintf(
'%s/%s--%s:%s/%s/%s/json?source=mix-obs&on_invalid=fill_with_invalid&use_decluttered=true',
$this->apiBaseUrl,
$startDate,
$endDate,
$duration,
$batchQueryString,
$metar
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
$statusCode = $response->getStatusCode();
$data = json_decode($response->getBody(), true);
if ($statusCode != 200) {
return $this->createErrorResponse($statusCode);
}
// Merge data from the current API call into the final data
$dataFinal['version'] = $data['version'];
$dataFinal['user'] = $data['user'];
$dataFinal['dateGenerated'] = $data['dateGenerated'];
$dataFinal['status'] = $data['status'];
$dataFinal['data'] = array_merge($dataFinal['data'] ?? [], $data['data']);
}
// Check if there is no comma in $metar
return $dataFinal;
}
public function getWeatherStationDataByHashId($metarData)
{
$response = [];
foreach ($metarData as &$metarParam) {
if (count($metarParam['coordinates']) > 0) {
foreach ($metarParam['coordinates'] as &$coordinates) {
$stationData = \Pimcore\Model\DataObject\WeatherStations::getByHash($coordinates['station_id'], true);
if ($stationData) {
$newData = [
'station_name' => $stationData->getName(),
'station_name_ar' => $stationData->getName('ar'),
'station_wmo_id' => $stationData->getWmoId(),
'station_alternativeIds' => $stationData->getAlternativeIds(),
];
// Append the new data to the existing coordinates without reindexing
$coordinates += $newData;
}
}
// Reset array keys to be sequential
$metarParam['coordinates'] = array_values($metarParam['coordinates']);
}
}
return $metarData;
}
// public function getWeatherStatioData($startDate, $endDate, $parameters, $hash, $genExcel, $translator, $interval = 'PT24H')
// {
// try {
// if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/', $startDate)) {
// throw new \InvalidArgumentException($translator->trans('invalid_start_date_format'));
// }
// if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/', $startDate)) {
// throw new \InvalidArgumentException($translator->trans('invalid_end_date_format'));
// }
// $cacheKey = \App\Lib\Utility::generateKey($startDate, $endDate, $parameters, $hash);
// $cachedData = $this->redisCache->get($cacheKey);
// if ($cachedData !== null && !$genExcel) {
// // Return the cached data if available
// return $cachedData;
// }
// $dataFinal = [];
// while (!empty($parameters)) {
// $batchParameters = array_splice($parameters, 0, 10); // Take up to 10 parameters
// $batchQueryString = implode(',', $batchParameters);
// $url = sprintf(
// "%s/%s--%s:%s/%s/%s/json?source=mix-obs&on_invalid=fill_with_invalid",
// $this->apiBaseUrl,
// $startDate,
// $endDate,
// $interval,
// $batchQueryString,
// $hash
// );
// $client = new Client(['verify' => false]);
// $response = $client->request('GET', $url, [
// 'auth' => [$this->username, $this->password],
// ]);
// $statusCode = $response->getStatusCode();
// $data = json_decode($response->getBody(), true);
// if ($statusCode != 200) {
// return $this->createErrorResponse($statusCode);
// }
// // Merge data from the current API call into the final data
// $dataFinal['version'] = $data['version'];
// $dataFinal['user'] = $data['user'];
// $dataFinal['dateGenerated'] = $data['dateGenerated'];
// $dataFinal['status'] = $data['status'];
// $dataFinal['data'] = array_merge($dataFinal['data'] ?? [], $data['data']);
// }
// if (count($dataFinal['data']) > 0) {
// $metarData = $this->getWeatherStationDataByHashId($dataFinal['data']);
// $dataFinal['data'] = $metarData;
// }
// if ($genExcel) {
// $csvData[] = ['parameter', 'station id', 'station name', 'date', 'value'];
// if (count($dataFinal['data']) > 0) {
// foreach ($dataFinal['data'] as $key => $value) {
// foreach ($value as $key1 => $value1) {
// if (!is_array($value1)) {
// $parameter = $value1;
// }
// if (is_array($value1)) {
// foreach ($value1 as $key2 => $value2) {
// $station_hash = $value2['station_id'];
// $station_name = $value2['station_name'];
// $station_id = $value2['station_alternativeIds'];
// if (is_array($value2['dates'])) {
// foreach ($value2['dates'] as $key3 => $value3) {
// $date = $value3['date'];
// $value = $value3['value'];
// $csvData[] = [$parameter, $station_id, $station_name, $date, $value];
// }
// }
// }
// }
// }
// }
// }
// $xlsxReport = \Pimcore\Model\Asset::getByPath("/report/StationCsv/historical_weather_data.xlsx");
// if ($xlsxReport !== null) {
// $xlsxReport->delete();
// }
// $excelData = ExcelGenerator::createAndSaveXlsx($csvData, "historical_weather_data", true, 'StationCsv');
// return $excelData;
// }
// // Set the data to Redis cache
// $this->redisCache->set($cacheKey, $dataFinal);
// return $dataFinal;
// } catch (RequestException $e) {
// throw new \Exception($e->getMessage());
// } catch (\Exception $e) {
// throw new \Exception($e->getMessage());
// }
// }
public function getWeatherStatioData($startDate, $endDate, $parameters, $hash, $genExcel, $translator, $interval = 'PT24H')
{
try {
if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/', $startDate)) {
throw new \InvalidArgumentException($translator->trans('invalid_start_date_format'));
}
if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/', $endDate)) {
throw new \InvalidArgumentException($translator->trans('invalid_end_date_format'));
}
$timeResolutions = [
'_24h' => '+1 day',
'_12h' => '+12 hours',
'_6h' => '+6 hours',
'_3h' => '+3 hours',
'_1h' => '+1 hour'
];
$adjustedParameters = [];
$nonAdjustedParameters = [];
foreach ($parameters as $parameter) {
$matched = false;
foreach ($timeResolutions as $key => $adjustment) {
if (strpos($parameter, $key) !== false) {
$matched = true;
$adjustedParameters[$adjustment][] = $parameter;
break;
}
}
if (!$matched) {
$nonAdjustedParameters[] = $parameter;
}
}
// Initialize $dataFinal
$dataFinal = [
'version' => null,
'user' => null,
'dateGenerated' => null,
'status' => null,
'data' => []
];
// Process adjusted parameters
foreach ($adjustedParameters as $adjustment => $params) {
$adjustedStartDate = (new \DateTime($startDate))->modify($adjustment)->format('Y-m-d\TH:i:s.v\Z');
$adjustedEndDate = (new \DateTime($endDate))->modify($adjustment)->format('Y-m-d\TH:i:s.v\Z');
$data = $this->fetchWeatherData($adjustedStartDate, $adjustedEndDate, $params, $hash, $interval);
// Revert dates to original range
if (isset($data['data']) && is_array($data['data'])) {
foreach ($data['data'] as &$datum) {
if (isset($datum['coordinates'][0]['dates']) && is_array($datum['coordinates'][0]['dates'])) {
foreach ($datum['coordinates'][0]['dates'] as &$date) {
if (isset($date['date'])) {
$date['date'] = (new \DateTime($date['date']))
->modify('-' . ltrim($adjustment, '+'))
->format('Y-m-d\TH:i:s.v\Z');
}
}
}
}
} else {
$data['data'] = []; // Ensure 'data' exists
}
// Merge into $dataFinal
if (empty($dataFinal['version'])) {
$dataFinal['version'] = $data['version'] ?? null;
$dataFinal['user'] = $data['user'] ?? null;
$dataFinal['dateGenerated'] = $data['dateGenerated'] ?? null;
$dataFinal['status'] = $data['status'] ?? null;
}
if (isset($data['data']) && is_array($data['data'])) {
$dataFinal['data'] = array_merge($dataFinal['data'], $data['data']);
}
}
// Process non-adjusted parameters
if (!empty($nonAdjustedParameters)) {
$data = $this->fetchWeatherData($startDate, $endDate, $nonAdjustedParameters, $hash, $interval);
if (isset($data['data']) && is_array($data['data'])) {
$dataFinal['data'] = array_merge($dataFinal['data'], $data['data']);
}
}
// Reorder data based on parameters
$dataFinal['data'] = isset($dataFinal['data']) && is_array($dataFinal['data'])
? $this->orderResults($dataFinal['data'], $parameters)
: [];
if (count($dataFinal['data']) > 0) {
$metarData = $this->getWeatherStationDataByHashId($dataFinal['data']);
$dataFinal['data'] = $metarData;
}
if ($genExcel) {
return $this->generateExcel($dataFinal);
}
return $dataFinal;
} catch (RequestException $e) {
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
private function fetchWeatherData($startDate, $endDate, $parameters, $hash, $interval)
{
$dataFinal = [];
while (!empty($parameters)) {
$batchParameters = array_splice($parameters, 0, 10);
$batchQueryString = implode(',', $batchParameters);
$url = sprintf(
"%s/%s--%s:%s/%s/%s/json?source=mix-obs&on_invalid=fill_with_invalid&use_decluttered=true",
$this->apiBaseUrl,
$startDate,
$endDate,
$interval,
$batchQueryString,
$hash
);
$client = new Client(['verify' => false]);
$response = $client->request('GET', $url, [
'auth' => [$this->username, $this->password],
]);
if ($response->getStatusCode() != 200) {
throw new \Exception("Failed to fetch data from API");
}
$data = json_decode($response->getBody(), true);
$dataFinal = array_merge_recursive($dataFinal, $data);
}
return $dataFinal;
}
private function generateExcel($data)
{
$csvData[] = ['parameter', 'station id', 'station name', 'date', 'value'];
if (count($data['data']) > 0) {
foreach ($data['data'] as $key => $value) {
foreach ($value as $key1 => $value1) {
if (!is_array($value1)) {
$parameter = $value1;
}
if (is_array($value1)) {
foreach ($value1 as $key2 => $value2) {
$station_hash = $value2['station_id'];
$station_name = $value2['station_name'];
$station_id = $value2['station_alternativeIds'];
if (is_array($value2['dates'])) {
foreach ($value2['dates'] as $key3 => $value3) {
$date = $value3['date'];
$value = $value3['value'];
$csvData[] = [$parameter, $station_id, $station_name, $date, $value];
}
}
}
}
}
}
}
$xlsxReport = \Pimcore\Model\Asset::getByPath("/report/StationCsv/historical_weather_data.xlsx");
if ($xlsxReport !== null) {
$xlsxReport->delete();
}
$excelData = ExcelGenerator::createAndSaveXlsx($csvData, "historical_weather_data", true, 'StationCsv');
return $excelData;
}
private function orderResults($data, $parameters)
{
$orderedResults = [];
foreach ($parameters as $parameter) {
foreach ($data as $key => $item) {
if ($item['parameter'] === $parameter) {
$orderedResults[] = $item;
break;
}
}
}
return $orderedResults;
}
// Assuming $data1 and $data2 contain the response data from URL1 and URL2 respectively
// and that the relevant date fields in these responses are in a format that can be converted to a timestamp
function adjustResponseDates(&$data, $hours)
{
error_log(print_r($data, true)); // Log the initial data
if ($hours == 24) {
$timeAdjustment = '-1 day';
} elseif ($hours == 1) {
$timeAdjustment = '-1 hour';
} elseif ($hours == 12) {
$timeAdjustment = '-12 hour';
} else {
$timeAdjustment = '';
}
foreach ($data as &$parameter) { // Iterate through each parameter
if ($timeAdjustment && isset($parameter['coordinates'])) {
foreach ($parameter['coordinates'] as $coordKey => $coordinate) {
if (isset($coordinate['dates']) && is_array($coordinate['dates'])) {
foreach ($coordinate['dates'] as $dateKey => $dateInfo) {
if (isset($dateInfo['date'])) {
// Create DateTime object with UTC timezone
$date = new DateTime($dateInfo['date'], new DateTimeZone('UTC'));
// Apply time adjustment
$date->modify($timeAdjustment);
// Format adjusted date in UTC
$adjustedDate = $date->format('Y-m-d\TH:i:s.v\Z');
// Update the date in the data
$parameter['coordinates'][$coordKey]['dates'][$dateKey]['date'] = $adjustedDate;
// Log the adjusted date
error_log("Adjusted Date: " . $adjustedDate);
}
}
}
}
}
}
unset($parameter); // Break the reference with the last element
error_log("Final Data: " . print_r($data, true)); // Log the final modified data
}
}