now = ($now ?? new \DateTimeImmutable('now'))->setTimezone(new \DateTimeZone($this->timezone)); } public function stationsData(): array { $at = fn(string $time) => (int) $this->now->modify($time)->format('U'); $today = fn(string $hm) => (int) $this->now->setTime((int) substr($hm, 0, 2), (int) substr($hm, 3, 2))->format('U'); 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, '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, '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, '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, '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]], ], ]]]; } public function measure(string $deviceId, string $moduleId, int $begin, int $end): array { $body = []; $count = count(self::RAIN_PER_DAY); foreach (self::RAIN_PER_DAY as $i => $mm) { $day = $this->now->setTime(3, 17)->modify('-' . ($count - 1 - $i) . ' days'); if ($day->getTimestamp() >= $begin) { $body[(string) $day->getTimestamp()] = [$mm]; } } 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 { $tmin = [11.0, 10.1, 11.3, 12.0, 9.4, 8.1]; $tmax = [17.9, 18.3, 20.1, 17.4, 15.2, 16.0]; $precipDay = [0.0, 0.4, 0.0, 8.2, 3.1, 0.2]; $dates = []; $hourlyTime = []; $hourlyTemp = []; $hourlyPrecip = []; $hourlyWind = []; $hourlyDir = []; for ($d = 0; $d < 6; $d++) { $day = $this->now->modify("+$d days"); $dates[] = $day->format('Y-m-d'); for ($h = 0; $h < 24; $h++) { $hourlyTime[] = $day->setTime($h, 0)->format('Y-m-d\TH:i'); $t = $tmin[$d] + ($tmax[$d] - $tmin[$d]) * (0.5 + 0.5 * sin((($h - 9) / 24) * 2 * M_PI)); $hourlyTemp[] = round($t, 1); $p = ($precipDay[$d] > 0 && $h >= 14 && $h <= 16) ? round($precipDay[$d] / 3, 1) : 0.0; $hourlyPrecip[] = $p; $hourlyWind[] = round(3 + 6 * (0.5 + 0.5 * sin((($h + $d * 3) / 24) * 2 * M_PI)), 1); $hourlyDir[] = ($d * 40 + $h * 7) % 360; } } return [ 'daily' => [ 'time' => $dates, 'weather_code' => [3, 2, 0, 61, 80, 95], 'temperature_2m_max' => $tmax, 'temperature_2m_min' => $tmin, 'precipitation_sum' => $precipDay, 'precipitation_probability_max' => [10, 20, 5, 80, 60, 15], ], 'hourly' => [ 'time' => $hourlyTime, 'temperature_2m' => $hourlyTemp, 'precipitation' => $hourlyPrecip, 'wind_speed_10m' => $hourlyWind, 'wind_direction_10m' => $hourlyDir, ], ]; } }