*/ private function body(): array { $json = json_decode((string) file_get_contents(__DIR__ . '/fixtures/getstationsdata.json'), true); return $json['body']; } public function testStationMetadata(): void { $m = StationMapper::map($this->body(), null, []); self::assertSame('Europe/Berlin', $m['timezone']); self::assertSame(51.82, $m['lat']); self::assertSame(6.55, $m['lon']); self::assertSame('70:ee:50:00:00:01', $m['device_id']); self::assertSame(1789129812, $m['measured_at']); } public function testOutdoor(): void { $m = StationMapper::map($this->body(), null, []); self::assertSame([ 'temp' => 16.4, 'trend' => 'down', 'min' => 9.2, 'min_at' => 1789099800, 'max' => 19.8, 'max_at' => 1789124700, 'humidity' => 71.0, ], $m['outdoor']); } public function testIndoorDefaultOrderAndUnreachableModule(): void { $m = StationMapper::map($this->body(), null, []); 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, '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 { $m = StationMapper::map($this->body(), null, [ '03:00:00:00:00:03' => 'Studeerkamer', '70:ee:50:00:00:01' => 'Living', ]); self::assertSame(['Studeerkamer', 'Living', 'Slaapkamer'], array_column($m['indoor'], 'name')); } public function testRainModule(): void { $m = StationMapper::map($this->body(), null, []); self::assertSame('05:00:00:00:00:04', $m['rain_module_id']); 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(); $body['devices'][0]['modules'] = array_values(array_filter( $body['devices'][0]['modules'], fn(array $mod) => $mod['type'] !== 'NAModule3', )); $m = StationMapper::map($body, null, []); self::assertNull($m['rain_module_id']); self::assertNull($m['sum_rain_24']); } public function testUnreachableOutdoorModuleGivesNulls(): void { $body = $this->body(); $body['devices'][0]['modules'][0]['reachable'] = false; 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, 'humidity' => null], $m['outdoor']); } public function testUnknownDeviceIdFallsBackToFirstStation(): void { $m = StationMapper::map($this->body(), 'ff:ff:ff:ff:ff:ff', []); self::assertSame('70:ee:50:00:00:01', $m['device_id']); } public function testEmptyDevicesGivesNullsWithoutCrashing(): void { $m = StationMapper::map(['devices' => []], null, []); self::assertNull($m['device_id']); self::assertNull($m['timezone']); self::assertNull($m['measured_at']); self::assertSame([], $m['indoor']); self::assertNull($m['outdoor']['temp']); self::assertNull($m['rain_module_id']); self::assertSame(['current' => null, 'trend' => null], $m['pressure']); } }