|
18 | 18 |
|
19 | 19 | namespace Cmfcmf; |
20 | 20 |
|
| 21 | +use Cmfcmf\OpenWeatherMap\AirPollution; |
21 | 22 | use Cmfcmf\OpenWeatherMap\CurrentWeather; |
22 | | -use Cmfcmf\OpenWeatherMap\UVIndex; |
23 | 23 | use Cmfcmf\OpenWeatherMap\CurrentWeatherGroup; |
24 | 24 | use Cmfcmf\OpenWeatherMap\Exception as OWMException; |
| 25 | +use Cmfcmf\OpenWeatherMap\NotFoundException as OWMNotFoundException; |
| 26 | +use Cmfcmf\OpenWeatherMap\UVIndex; |
25 | 27 | use Cmfcmf\OpenWeatherMap\WeatherForecast; |
26 | 28 | use Psr\Cache\CacheItemPoolInterface; |
27 | 29 | use Psr\Http\Client\ClientInterface; |
@@ -67,6 +69,11 @@ class OpenWeatherMap |
67 | 69 | */ |
68 | 70 | private $uvIndexUrl = 'https://api.openweathermap.org/data/2.5/uvi'; |
69 | 71 |
|
| 72 | + /** |
| 73 | + * @var string The basic api url to fetch air pollution data from. |
| 74 | + */ |
| 75 | + private $airPollutionUrl = 'https://api.openweathermap.org/pollution/v1/'; |
| 76 | + |
70 | 77 | /** |
71 | 78 | * @var CacheItemPoolInterface|null $cache The cache to use. |
72 | 79 | */ |
@@ -336,6 +343,45 @@ public function getHistoricUVIndex($lat, $lon, $start, $end) |
336 | 343 | }, $data); |
337 | 344 | } |
338 | 345 |
|
| 346 | + /** |
| 347 | + * Returns air pollution data |
| 348 | + * |
| 349 | + * @param string $type One of CO, O3, SO2, and NO2. |
| 350 | + * @param string $lat The location's latitude. |
| 351 | + * @param string $lon The location's longitude. |
| 352 | + * @param string $date The date to gather data from. If you omit this parameter or supply "current", returns current data. |
| 353 | + * |
| 354 | + * @return AirPollution\COAirPollution|AirPollution\NO2AirPollution|AirPollution\O3AirPollution|AirPollution\SO2AirPollution|null The air pollution data or null if no data was found. |
| 355 | + * |
| 356 | + * We use strings as $lat and $lon, since the exact number of digits in $lat and $lon determines the search range. |
| 357 | + * For example, there is a difference between using "1.5" and "1.5000". |
| 358 | + * We also use a string for $date, since it may either be "current" or an (abbreviated) ISO 8601 timestamp like 2016Z. |
| 359 | + * |
| 360 | + * @throws OWMException|\Exception |
| 361 | + * |
| 362 | + * @api |
| 363 | + */ |
| 364 | + public function getAirPollution($type, $lat, $lon, $date = "current") |
| 365 | + { |
| 366 | + $answer = $this->getRawAirPollutionData($type, $lat, $lon, $date); |
| 367 | + if ($answer === null) { |
| 368 | + return null; |
| 369 | + } |
| 370 | + $json = $this->parseJson($answer); |
| 371 | + switch ($type) { |
| 372 | + case "O3": |
| 373 | + return new AirPollution\O3AirPollution($json); |
| 374 | + case "NO2": |
| 375 | + return new AirPollution\NO2AirPollution($json); |
| 376 | + case "SO2": |
| 377 | + return new AirPollution\SO2AirPollution($json); |
| 378 | + case "CO": |
| 379 | + return new AirPollution\COAirPollution($json); |
| 380 | + default: |
| 381 | + throw new \LogicException(); |
| 382 | + } |
| 383 | + } |
| 384 | + |
339 | 385 | /** |
340 | 386 | * Directly returns the xml/json/html string returned by OpenWeatherMap for the current weather. |
341 | 387 | * |
@@ -471,6 +517,40 @@ public function getRawUVIndexData($mode, $lat, $lon, $cnt = null, $start = null, |
471 | 517 | return $this->cacheOrFetchResult($url); |
472 | 518 | } |
473 | 519 |
|
| 520 | + /** |
| 521 | + * Fetch raw air pollution data |
| 522 | + * |
| 523 | + * @param string $type One of CO, O3, SO2, and NO2. |
| 524 | + * @param string $lat The location's latitude. |
| 525 | + * @param string $lon The location's longitude. |
| 526 | + * @param string $date The date to gather data from. If you omit this parameter or supply "current", returns current data. |
| 527 | + * |
| 528 | + * @return string|null The air pollution data or null if no data was found. |
| 529 | + * |
| 530 | + * We use strings as $lat and $lon, since the exact number of digits in $lat and $lon determines the search range. |
| 531 | + * For example, there is a difference between using "1.5" and "1.5000". |
| 532 | + * We also use a string for $date, since it may either be "current" or an (abbreviated) ISO 8601 timestamp like 2016Z. |
| 533 | + * |
| 534 | + * @api |
| 535 | + */ |
| 536 | + public function getRawAirPollutionData($type, $lat, $lon, $date = "current") |
| 537 | + { |
| 538 | + if (!in_array($type, ["CO", "O3", "SO2", "NO2"])) { |
| 539 | + throw new \InvalidArgumentException('Invalid $type received.'); |
| 540 | + } |
| 541 | + if (!is_string($lat) || !is_string($lon) || !is_string($date)) { |
| 542 | + throw new \InvalidArgumentException('$lat, $lon and $date all must be strings.'); |
| 543 | + } |
| 544 | + |
| 545 | + $url = $this->airPollutionUrl . strtolower($type) . "/$lat,$lon/$date.json?appid=" . $this->apiKey; |
| 546 | + |
| 547 | + try { |
| 548 | + return $this->cacheOrFetchResult($url); |
| 549 | + } catch (OWMNotFoundException $e) { |
| 550 | + return null; |
| 551 | + } |
| 552 | + } |
| 553 | + |
474 | 554 | /** |
475 | 555 | * Returns whether or not the last result was fetched from the cache. |
476 | 556 | * |
@@ -505,7 +585,10 @@ private function cacheOrFetchResult($url) |
505 | 585 | $response = $this->httpClient->sendRequest($this->httpRequestFactory->createRequest("GET", $url)); |
506 | 586 | $result = $response->getBody()->getContents(); |
507 | 587 | if ($response->getStatusCode() !== 200) { |
508 | | - throw new OWMException('OpenWeatherMap returned a response with status code ' . $response->getStatusCode() . ' and the following content '. $result); |
| 588 | + if ($result === "{\"message\":\"not found\"}\n" && $response->getStatusCode() === 404) { |
| 589 | + throw new OWMNotFoundException(); |
| 590 | + } |
| 591 | + throw new OWMException('OpenWeatherMap returned a response with status code ' . $response->getStatusCode() . ' and the following content `'. $result . '`'); |
509 | 592 | } |
510 | 593 |
|
511 | 594 | if ($this->cache !== null) { |
|
0 commit comments