diff --git a/config.example.php b/config.example.php index f5aa056..c117d55 100644 --- a/config.example.php +++ b/config.example.php @@ -30,6 +30,7 @@ return [ 'cache_ttl' => [ 'stations' => 300, 'measure' => 900, + 'pressure' => 900, 'forecast' => 3600, ], diff --git a/src/Config.php b/src/Config.php index 8b554cc..79b61e2 100644 --- a/src/Config.php +++ b/src/Config.php @@ -18,6 +18,7 @@ final class Config 'cache_ttl' => [ 'stations' => 300, 'measure' => 900, + 'pressure' => 900, 'forecast' => 3600, ], 'storage_path' => null, diff --git a/src/DashboardService.php b/src/DashboardService.php index 5ec842f..271194a 100644 --- a/src/DashboardService.php +++ b/src/DashboardService.php @@ -18,7 +18,7 @@ final class DashboardService private array $errors = []; /** - * @param array{stations: int, measure: int, forecast: int} $ttl + * @param array{stations: int, measure: int, pressure: int, forecast: int} $ttl * @param array $indoorModules */ public function __construct( @@ -47,6 +47,7 @@ final class DashboardService $now = $nowUtc->setTimezone($tz); $rain = $this->rain($station, $now); + $pressure = $this->pressure($station, $now); $forecast = $this->forecast($station, $tz); return [ @@ -63,9 +64,11 @@ final class DashboardService 'min_at' => $this->iso($station['outdoor']['min_at'], $tz), 'max' => $station['outdoor']['max'], 'max_at' => $this->iso($station['outdoor']['max_at'], $tz), + 'humidity' => $station['outdoor']['humidity'], ], 'indoor' => $station['indoor'], 'rain' => $rain, + 'pressure' => $pressure, 'forecast' => $forecast['days'], 'forecast_stale' => $forecast['stale'], 'errors' => $this->errors, @@ -91,6 +94,25 @@ final class DashboardService return RainCalculator::compute($measure['data'], $now, $station['sum_rain_24']) + ['stale' => $measure['stale']]; } + /** @return array{current: ?float, trend: ?string, history: list, stale: bool} */ + private function pressure(array $station, \DateTimeImmutable $now): array + { + $base = ['current' => $station['pressure']['current'], 'trend' => $station['pressure']['trend']]; + if ($station['device_id'] === null) { + return $base + ['history' => [], 'stale' => false]; + } + $begin = $now->getTimestamp() - PressureHistory::HOURS * 3600; + $measure = $this->fetch( + 'pressure', + fn() => $this->source->pressureHistory($station['device_id'], $begin, $now->getTimestamp()), + self::ERR_NETATMO, + ); + return $base + [ + 'history' => $measure['data'] === null ? [] : PressureHistory::map($measure['data'], $now->getTimezone()), + 'stale' => $measure['stale'], + ]; + } + /** @return array{days: list, stale: bool} */ private function forecast(array $station, \DateTimeZone $tz): array { diff --git a/src/FixtureSource.php b/src/FixtureSource.php index 29cd13f..6ee8f5e 100644 --- a/src/FixtureSource.php +++ b/src/FixtureSource.php @@ -27,16 +27,17 @@ final class FixtureSource implements WeatherSource return ['devices' => [[ '_id' => '70:ee:50:00:00:01', 'type' => 'NAMain', 'station_name' => 'Thuis', 'module_name' => 'Woonkamer', 'reachable' => true, 'place' => ['timezone' => $this->timezone, 'location' => [6.55, 51.82]], - 'dashboard_data' => ['time_utc' => $at('-2 minutes'), 'Temperature' => 21.3, 'min_temp' => 20.4, 'max_temp' => 22.1, - 'date_min_temp' => $today('05:50'), 'date_max_temp' => $today('13:40'), 'temp_trend' => 'stable'], + 'dashboard_data' => ['time_utc' => $at('-2 minutes'), 'Temperature' => 21.3, 'CO2' => 612, 'Humidity' => 48, + 'Pressure' => 1014.2, 'AbsolutePressure' => 1011.8, 'pressure_trend' => 'up', 'Noise' => 38, + 'min_temp' => 20.4, 'max_temp' => 22.1, 'date_min_temp' => $today('05:50'), 'date_max_temp' => $today('13:40'), 'temp_trend' => 'stable'], 'modules' => [ ['_id' => '02:00:00:00:00:01', 'type' => 'NAModule1', 'module_name' => 'Buiten', 'reachable' => true, - 'dashboard_data' => ['time_utc' => $at('-3 minutes'), 'Temperature' => 16.4, 'min_temp' => 9.2, 'max_temp' => 19.8, + 'dashboard_data' => ['time_utc' => $at('-3 minutes'), 'Temperature' => 16.4, 'Humidity' => 71, 'min_temp' => 9.2, 'max_temp' => 19.8, 'date_min_temp' => $today('06:10'), 'date_max_temp' => $today('13:05'), 'temp_trend' => 'down']], ['_id' => '03:00:00:00:00:02', 'type' => 'NAModule4', 'module_name' => 'Slaapkamer', 'reachable' => true, - 'dashboard_data' => ['time_utc' => $at('-4 minutes'), 'Temperature' => 18.9, 'min_temp' => 18.1, 'max_temp' => 19.6, 'temp_trend' => 'up']], + 'dashboard_data' => ['time_utc' => $at('-4 minutes'), 'Temperature' => 18.9, 'CO2' => 1180, 'Humidity' => 52, 'min_temp' => 18.1, 'max_temp' => 19.6, 'temp_trend' => 'up']], ['_id' => '03:00:00:00:00:03', 'type' => 'NAModule4', 'module_name' => 'Kantoor', 'reachable' => true, - 'dashboard_data' => ['time_utc' => $at('-4 minutes'), 'Temperature' => 20.2, 'min_temp' => 19.0, 'max_temp' => 21.0, 'temp_trend' => 'stable']], + 'dashboard_data' => ['time_utc' => $at('-4 minutes'), 'Temperature' => 20.2, 'CO2' => 1640, 'Humidity' => 44, 'min_temp' => 19.0, 'max_temp' => 21.0, 'temp_trend' => 'stable']], ['_id' => '05:00:00:00:00:04', 'type' => 'NAModule3', 'module_name' => 'Regenmeter', 'reachable' => true, 'dashboard_data' => ['time_utc' => $at('-3 minutes'), 'Rain' => 0, 'sum_rain_1' => 0, 'sum_rain_24' => 2.4]], ], @@ -56,6 +57,16 @@ final class FixtureSource implements WeatherSource return $body; } + public function pressureHistory(string $deviceId, int $begin, int $end): array + { + $body = []; + for ($ts = $begin - ($begin % 1800); $ts <= $end; $ts += 1800) { + $i = ($end - $ts) / 1800; + $body[(string) $ts] = [round(1012 + 3 * sin($i / 8) + ($i % 5) * 0.1, 1)]; + } + return $body; + } + public function forecast(float $lat, float $lon, string $timezone): array { $dates = []; diff --git a/src/LiveSource.php b/src/LiveSource.php index 2a56a4f..b2e3acb 100644 --- a/src/LiveSource.php +++ b/src/LiveSource.php @@ -34,6 +34,11 @@ final class LiveSource implements WeatherSource return $this->netatmo->getMeasure($deviceId, $moduleId, $begin, $end); } + public function pressureHistory(string $deviceId, int $begin, int $end): array + { + return $this->netatmo->getPressureHistory($deviceId, $begin, $end); + } + public function forecast(float $lat, float $lon, string $timezone): array { return $this->openMeteo->dailyForecast($lat, $lon, $timezone); diff --git a/src/NetatmoClient.php b/src/NetatmoClient.php index d66bb32..ae4b0db 100644 --- a/src/NetatmoClient.php +++ b/src/NetatmoClient.php @@ -57,6 +57,24 @@ final class NetatmoClient return $json['body']; } + /** @return array timestamp => [hPa], per 30 minuten, van het basisstation */ + public function getPressureHistory(string $deviceId, int $begin, int $end): array + { + $json = $this->apiGet('getmeasure', [ + 'device_id' => $deviceId, + 'scale' => '30min', + 'type' => 'Pressure', + 'date_begin' => $begin, + 'date_end' => $end, + 'optimize' => 'false', + 'real_time' => 'false', + ]); + if (!is_array($json['body'] ?? null)) { + throw new UpstreamException('getmeasure (Pressure): geen body in antwoord'); + } + return $json['body']; + } + /** @param array $query */ private function apiGet(string $path, array $query): array { diff --git a/src/PressureHistory.php b/src/PressureHistory.php new file mode 100644 index 0000000..ec4d622 --- /dev/null +++ b/src/PressureHistory.php @@ -0,0 +1,33 @@ + $body + * @return list + */ + public static function map(array $body, \DateTimeZone $tz): array + { + $points = []; + foreach ($body as $timestamp => $values) { + if (!is_numeric($timestamp) || !is_array($values) || !isset($values[0]) || !is_numeric($values[0])) { + continue; + } + $points[(int) $timestamp] = (float) $values[0]; + } + ksort($points); + + $out = []; + foreach ($points as $ts => $hpa) { + $out[] = ['at' => (new \DateTimeImmutable('@' . $ts))->setTimezone($tz)->format(\DATE_ATOM), 'hpa' => $hpa]; + } + return $out; + } +} diff --git a/src/StationMapper.php b/src/StationMapper.php index ff9a0b0..d66f40a 100644 --- a/src/StationMapper.php +++ b/src/StationMapper.php @@ -10,14 +10,16 @@ namespace Weerscherm; */ final class StationMapper { - private const EMPTY_OUTDOOR = ['temp' => null, 'trend' => null, 'min' => null, 'min_at' => null, 'max' => null, 'max_at' => null]; + private const EMPTY_OUTDOOR = ['temp' => null, 'trend' => null, 'min' => null, 'min_at' => null, 'max' => null, 'max_at' => null, 'humidity' => null]; + private const EMPTY_PRESSURE = ['current' => null, 'trend' => null]; /** * @param array $body * @param array $indoorModules _id => label, in de gewenste volgorde * @return array{timezone: ?string, lat: ?float, lon: ?float, device_id: ?string, measured_at: ?int, - * outdoor: array{temp: ?float, trend: ?string, min: ?float, min_at: ?int, max: ?float, max_at: ?int}, - * indoor: list, + * outdoor: array{temp: ?float, trend: ?string, min: ?float, min_at: ?int, max: ?float, max_at: ?int, humidity: ?float}, + * indoor: list, + * pressure: array{current: ?float, trend: ?string}, * rain_module_id: ?string, sum_rain_24: ?float} */ public static function map(array $body, ?string $deviceId, array $indoorModules): array @@ -26,7 +28,8 @@ final class StationMapper if ($device === null) { return [ 'timezone' => null, 'lat' => null, 'lon' => null, 'device_id' => null, 'measured_at' => null, - 'outdoor' => self::EMPTY_OUTDOOR, 'indoor' => [], 'rain_module_id' => null, 'sum_rain_24' => null, + 'outdoor' => self::EMPTY_OUTDOOR, 'indoor' => [], 'pressure' => self::EMPTY_PRESSURE, + 'rain_module_id' => null, 'sum_rain_24' => null, ]; } @@ -43,6 +46,10 @@ final class StationMapper 'measured_at' => self::intOrNull(self::dashboard($device)['time_utc'] ?? self::dashboard($outdoor)['time_utc'] ?? null), 'outdoor' => self::mapOutdoor($outdoor), 'indoor' => self::mapIndoor($device, $modules, $indoorModules), + 'pressure' => [ + 'current' => self::floatOrNull(self::dashboard($device)['Pressure'] ?? null), + 'trend' => self::stringOrNull(self::dashboard($device)['pressure_trend'] ?? null), + ], 'rain_module_id' => $rain === null ? null : self::stringOrNull($rain['_id'] ?? null), 'sum_rain_24' => self::floatOrNull(self::dashboard($rain)['sum_rain_24'] ?? null), ]; @@ -92,6 +99,7 @@ final class StationMapper 'min_at' => self::intOrNull($d['date_min_temp'] ?? null), 'max' => self::floatOrNull($d['max_temp'] ?? null), 'max_at' => self::intOrNull($d['date_max_temp'] ?? null), + 'humidity' => self::floatOrNull($d['Humidity'] ?? null), ]; } @@ -118,6 +126,8 @@ final class StationMapper 'temp' => self::floatOrNull($d['Temperature'] ?? null), 'min' => self::floatOrNull($d['min_temp'] ?? null), 'max' => self::floatOrNull($d['max_temp'] ?? null), + 'humidity' => self::floatOrNull($d['Humidity'] ?? null), + 'co2' => self::intOrNull($d['CO2'] ?? null), 'reachable' => $d !== [], ]; } diff --git a/src/WeatherSource.php b/src/WeatherSource.php index 4c83cfb..e2991c2 100644 --- a/src/WeatherSource.php +++ b/src/WeatherSource.php @@ -13,6 +13,9 @@ interface WeatherSource /** @return array de "body" van Netatmo getmeasure (timestamp => [mm]) */ public function measure(string $deviceId, string $moduleId, int $begin, int $end): array; + /** @return array de "body" van Netatmo getmeasure (timestamp => [hPa]) voor het basisstation */ + public function pressureHistory(string $deviceId, int $begin, int $end): array; + /** @return array het "daily"-blok van Open-Meteo */ public function forecast(float $lat, float $lon, string $timezone): array; } diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 63d838c..6ea3a3e 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -28,7 +28,7 @@ final class ConfigTest extends TestCase self::assertSame('Europe/Berlin', $config->get('timezone')); self::assertSame('fixture', $config->get('data_source')); - self::assertSame(['stations' => 300, 'measure' => 900, 'forecast' => 3600], $config->get('cache_ttl')); + self::assertSame(['stations' => 300, 'measure' => 900, 'pressure' => 900, 'forecast' => 3600], $config->get('cache_ttl')); self::assertSame([], $config->get('indoor_modules')); self::assertNull($config->get('netatmo_device_id')); } @@ -39,7 +39,7 @@ final class ConfigTest extends TestCase $config = Config::load($this->file); self::assertSame('Europe/Amsterdam', $config->get('timezone')); - self::assertSame(['stations' => 60, 'measure' => 900, 'forecast' => 3600], $config->get('cache_ttl')); + self::assertSame(['stations' => 60, 'measure' => 900, 'pressure' => 900, 'forecast' => 3600], $config->get('cache_ttl')); } public function testUnknownKeyReturnsGivenDefault(): void diff --git a/tests/DashboardServiceTest.php b/tests/DashboardServiceTest.php index 1e2e058..80d1a24 100644 --- a/tests/DashboardServiceTest.php +++ b/tests/DashboardServiceTest.php @@ -32,7 +32,7 @@ final class DashboardServiceTest extends TestCase return new DashboardService( $this->source, new Cache($this->dir), - ['stations' => 300, 'measure' => 900, 'forecast' => 3600], + ['stations' => 300, 'measure' => 900, 'pressure' => 900, 'forecast' => 3600], 'Europe/Amsterdam', $lat, $lon, @@ -46,12 +46,19 @@ final class DashboardServiceTest extends TestCase { $p = $this->service()->build(); - self::assertSame(['generated_at', 'timezone', 'station', 'outdoor', 'indoor', 'rain', 'forecast', 'forecast_stale', 'errors'], array_keys($p)); + self::assertSame(['generated_at', 'timezone', 'station', 'outdoor', 'indoor', 'rain', 'pressure', 'forecast', 'forecast_stale', 'errors'], array_keys($p)); self::assertSame('2026-09-11T14:32:05+02:00', $p['generated_at']); self::assertSame('Europe/Berlin', $p['timezone']); self::assertSame(['measured_at' => '2026-09-11T14:30:12+02:00', 'stale' => false], $p['station']); - self::assertSame(['temp' => 16.4, 'trend' => 'down', 'min' => 9.2, 'min_at' => '2026-09-11T06:10:00+02:00', 'max' => 19.8, 'max_at' => '2026-09-11T13:05:00+02:00'], $p['outdoor']); + self::assertSame(['temp' => 16.4, 'trend' => 'down', 'min' => 9.2, 'min_at' => '2026-09-11T06:10:00+02:00', 'max' => 19.8, 'max_at' => '2026-09-11T13:05:00+02:00', 'humidity' => 71.0], $p['outdoor']); self::assertCount(3, $p['indoor']); + self::assertSame(612, $p['indoor'][0]['co2']); + self::assertSame(48.0, $p['indoor'][0]['humidity']); + self::assertSame(1014.2, $p['pressure']['current']); + self::assertSame('up', $p['pressure']['trend']); + self::assertCount(49, $p['pressure']['history']); + self::assertSame('2026-09-10T14:30:00+02:00', $p['pressure']['history'][0]['at']); + self::assertFalse($p['pressure']['stale']); self::assertSame(2.4, $p['rain']['today']); self::assertSame(['2026-09-08', '2026-09-09', '2026-09-10'], array_column($p['rain']['previous_days'], 'date')); self::assertEqualsWithDelta(38.5, $p['rain']['month_total'], 0.0001); @@ -73,6 +80,29 @@ final class DashboardServiceTest extends TestCase self::assertSame((new \DateTimeImmutable('2026-09-11 12:32:05 UTC'))->getTimestamp(), $end); } + public function testPressureHistoryIsRequestedForLast24Hours(): void + { + $this->service()->build(); + + [$deviceId, $begin, $end] = $this->source->lastArgs['pressure']; + $now = (new \DateTimeImmutable('2026-09-11 12:32:05 UTC'))->getTimestamp(); + self::assertSame('70:ee:50:00:00:01', $deviceId); + self::assertSame($now - 86400, $begin); + self::assertSame($now, $end); + } + + public function testPressureFailureKeepsCurrentValueAndMarksStale(): void + { + $this->source->responses['pressure'] = new UpstreamException('500'); + + $p = $this->service()->build(); + + self::assertSame(1014.2, $p['pressure']['current']); + self::assertSame([], $p['pressure']['history']); + self::assertTrue($p['pressure']['stale']); + self::assertSame(['netatmo_unavailable'], $p['errors']); + } + public function testForecastUsesStationLocationUnlessConfigured(): void { $this->service()->build(); @@ -96,6 +126,8 @@ final class DashboardServiceTest extends TestCase self::assertSame([], $p['indoor']); self::assertNull($p['rain']['today']); self::assertSame(0, $this->source->calls['measure'], 'zonder regenmeter-id geen getmeasure-call'); + self::assertSame(0, $this->source->calls['pressure'], 'zonder device-id geen luchtdruk-call'); + self::assertSame(['current' => null, 'trend' => null, 'history' => [], 'stale' => false], $p['pressure']); self::assertSame('Europe/Amsterdam', $p['timezone'], 'fallback-tijdzone uit config'); self::assertSame(['netatmo_unavailable', 'forecast_unavailable'], $p['errors']); } @@ -152,7 +184,7 @@ final class DashboardServiceTest extends TestCase $this->service()->build(); $this->service('2026-09-11 12:36:05 UTC')->build(); - self::assertSame(['stations' => 1, 'measure' => 1, 'forecast' => 1], $this->source->calls); + self::assertSame(['stations' => 1, 'measure' => 1, 'pressure' => 1, 'forecast' => 1], $this->source->calls); $this->service('2026-09-11 12:38:05 UTC')->build(); self::assertSame(2, $this->source->calls['stations'], 'stations na 5 min opnieuw'); diff --git a/tests/FakeSource.php b/tests/FakeSource.php index d496992..151f4a7 100644 --- a/tests/FakeSource.php +++ b/tests/FakeSource.php @@ -13,7 +13,7 @@ final class FakeSource implements WeatherSource public array $responses = []; /** @var array */ - public array $calls = ['stations' => 0, 'measure' => 0, 'forecast' => 0]; + public array $calls = ['stations' => 0, 'measure' => 0, 'pressure' => 0, 'forecast' => 0]; /** @var array */ public array $lastArgs = []; @@ -24,6 +24,7 @@ final class FakeSource implements WeatherSource $s->responses = [ 'stations' => json_decode((string) file_get_contents(__DIR__ . '/fixtures/getstationsdata.json'), true)['body'], 'measure' => json_decode((string) file_get_contents(__DIR__ . '/fixtures/getmeasure.json'), true)['body'], + 'pressure' => json_decode((string) file_get_contents(__DIR__ . '/fixtures/getmeasure-pressure.json'), true)['body'], 'forecast' => json_decode((string) file_get_contents(__DIR__ . '/fixtures/forecast.json'), true)['daily'], ]; return $s; @@ -39,6 +40,11 @@ final class FakeSource implements WeatherSource return $this->answer('measure', func_get_args()); } + public function pressureHistory(string $deviceId, int $begin, int $end): array + { + return $this->answer('pressure', func_get_args()); + } + public function forecast(float $lat, float $lon, string $timezone): array { return $this->answer('forecast', func_get_args()); diff --git a/tests/NetatmoClientTest.php b/tests/NetatmoClientTest.php index 52985f4..8191320 100644 --- a/tests/NetatmoClientTest.php +++ b/tests/NetatmoClientTest.php @@ -198,4 +198,18 @@ final class NetatmoClientTest extends TestCase 'date_begin' => 1000, 'date_end' => 2000, 'optimize' => 'false', 'real_time' => 'false', ], $this->http->requests[0]['params']); } + + public function testGetPressureHistoryQuery(): void + { + $this->store->write(['access_token' => 'A1', 'refresh_token' => 'R1', 'expires_at' => self::NOW + 3600]); + $this->http->queue(200, json_decode((string) file_get_contents(__DIR__ . '/fixtures/getmeasure-pressure.json'), true)); + + $body = $this->client()->getPressureHistory('dev', 1000, 2000); + + self::assertCount(49, $body); + self::assertSame([ + 'device_id' => 'dev', 'scale' => '30min', 'type' => 'Pressure', + 'date_begin' => 1000, 'date_end' => 2000, 'optimize' => 'false', 'real_time' => 'false', + ], $this->http->requests[0]['params']); + } } diff --git a/tests/PressureHistoryTest.php b/tests/PressureHistoryTest.php new file mode 100644 index 0000000..031dfa6 --- /dev/null +++ b/tests/PressureHistoryTest.php @@ -0,0 +1,32 @@ + [1000.0], '1789129800' => ['x'], '1789133400' => [1013.5]], new \DateTimeZone('UTC')); + + self::assertSame([['at' => '2026-09-11T13:30:00+00:00', 'hpa' => 1013.5]], $points); + } +} diff --git a/tests/StationMapperTest.php b/tests/StationMapperTest.php index ffa9db8..6829ac8 100644 --- a/tests/StationMapperTest.php +++ b/tests/StationMapperTest.php @@ -38,6 +38,7 @@ final class StationMapperTest extends TestCase 'min_at' => 1789099800, 'max' => 19.8, 'max_at' => 1789124700, + 'humidity' => 71.0, ], $m['outdoor']); } @@ -47,8 +48,8 @@ final class StationMapperTest extends TestCase self::assertCount(3, $m['indoor']); self::assertSame(['Woonkamer', 'Slaapkamer', 'Kantoor'], array_column($m['indoor'], 'name')); - self::assertSame(['id' => '70:ee:50:00:00:01', 'name' => 'Woonkamer', 'temp' => 21.3, 'min' => 20.4, 'max' => 22.1, 'reachable' => true], $m['indoor'][0]); - self::assertSame(['id' => '03:00:00:00:00:03', 'name' => 'Kantoor', 'temp' => null, 'min' => null, 'max' => null, 'reachable' => false], $m['indoor'][2]); + self::assertSame(['id' => '70:ee:50:00:00:01', 'name' => 'Woonkamer', 'temp' => 21.3, 'min' => 20.4, 'max' => 22.1, 'humidity' => 48.0, 'co2' => 612, 'reachable' => true], $m['indoor'][0]); + self::assertSame(['id' => '03:00:00:00:00:03', 'name' => 'Kantoor', 'temp' => null, 'min' => null, 'max' => null, 'humidity' => null, 'co2' => null, 'reachable' => false], $m['indoor'][2]); } public function testIndoorConfigDeterminesOrderAndLabels(): void @@ -69,6 +70,24 @@ final class StationMapperTest extends TestCase self::assertSame(2.4, $m['sum_rain_24']); } + public function testPressureFromBaseStation(): void + { + $m = StationMapper::map($this->body(), null, []); + + self::assertSame(['current' => 1014.2, 'trend' => 'up'], $m['pressure']); + } + + public function testPressureNullWhenBaseStationUnreachable(): void + { + $body = $this->body(); + $body['devices'][0]['reachable'] = false; + unset($body['devices'][0]['dashboard_data']); + $m = StationMapper::map($body, null, []); + + self::assertSame(['current' => null, 'trend' => null], $m['pressure']); + self::assertSame(1789129780, $m['measured_at'], 'valt terug op time_utc van de buitenmodule'); + } + public function testWithoutRainModule(): void { $body = $this->body(); @@ -89,7 +108,7 @@ final class StationMapperTest extends TestCase unset($body['devices'][0]['modules'][0]['dashboard_data']); $m = StationMapper::map($body, null, []); - self::assertSame(['temp' => null, 'trend' => null, 'min' => null, 'min_at' => null, 'max' => null, 'max_at' => null], $m['outdoor']); + self::assertSame(['temp' => null, 'trend' => null, 'min' => null, 'min_at' => null, 'max' => null, 'max_at' => null, 'humidity' => null], $m['outdoor']); } public function testUnknownDeviceIdFallsBackToFirstStation(): void @@ -108,5 +127,6 @@ final class StationMapperTest extends TestCase self::assertSame([], $m['indoor']); self::assertNull($m['outdoor']['temp']); self::assertNull($m['rain_module_id']); + self::assertSame(['current' => null, 'trend' => null], $m['pressure']); } } diff --git a/tests/fixtures/getmeasure-pressure.json b/tests/fixtures/getmeasure-pressure.json new file mode 100644 index 0000000..4ec085f --- /dev/null +++ b/tests/fixtures/getmeasure-pressure.json @@ -0,0 +1,152 @@ +{ + "body": { + "1789043400": [ + 1011.5 + ], + "1789045200": [ + 1011 + ], + "1789047000": [ + 1010.6 + ], + "1789048800": [ + 1010.2 + ], + "1789050600": [ + 1010.3 + ], + "1789052400": [ + 1009.9 + ], + "1789054200": [ + 1009.6 + ], + "1789056000": [ + 1009.4 + ], + "1789057800": [ + 1009.1 + ], + "1789059600": [ + 1009.4 + ], + "1789061400": [ + 1009.3 + ], + "1789063200": [ + 1009.2 + ], + "1789065000": [ + 1009.2 + ], + "1789066800": [ + 1009.2 + ], + "1789068600": [ + 1009.7 + ], + "1789070400": [ + 1009.8 + ], + "1789072200": [ + 1009.9 + ], + "1789074000": [ + 1010.1 + ], + "1789075800": [ + 1010.3 + ], + "1789077600": [ + 1011 + ], + "1789079400": [ + 1011.2 + ], + "1789081200": [ + 1011.5 + ], + "1789083000": [ + 1011.8 + ], + "1789084800": [ + 1012 + ], + "1789086600": [ + 1012.8 + ], + "1789088400": [ + 1013.1 + ], + "1789090200": [ + 1013.3 + ], + "1789092000": [ + 1013.6 + ], + "1789093800": [ + 1013.8 + ], + "1789095600": [ + 1014.5 + ], + "1789097400": [ + 1014.6 + ], + "1789099200": [ + 1014.8 + ], + "1789101000": [ + 1014.8 + ], + "1789102800": [ + 1014.9 + ], + "1789104600": [ + 1015.4 + ], + "1789106400": [ + 1015.3 + ], + "1789108200": [ + 1015.2 + ], + "1789110000": [ + 1015 + ], + "1789111800": [ + 1014.8 + ], + "1789113600": [ + 1015.1 + ], + "1789115400": [ + 1014.8 + ], + "1789117200": [ + 1014.5 + ], + "1789119000": [ + 1014.1 + ], + "1789120800": [ + 1013.8 + ], + "1789122600": [ + 1013.8 + ], + "1789124400": [ + 1013.4 + ], + "1789126200": [ + 1012.9 + ], + "1789128000": [ + 1012.5 + ], + "1789129800": [ + 1012 + ] + }, + "status": "ok" +}