From 0ae1bdf76bda5c673d911fe15901637a3bf5c385 Mon Sep 17 00:00:00 2001 From: Tim Lappe Date: Sun, 23 Mar 2025 14:26:17 +0100 Subject: [PATCH] Fixed performance --- src/Controller/CalendarController.php | 4 +- .../Services/Home/HomeEntityInterface.php | 22 ----- .../Services/Home/HomeServiceInterface.php | 14 --- src/HomeAssistant/EntityState.php | 12 --- src/HomeAssistant/HomeAssistantClient.php | 25 ------ .../HomeAssistantHomeService.php | 90 +------------------ src/Service/CalendarExportService.php | 59 ++++++++---- src/Service/CalendarService.php | 18 +++- 8 files changed, 62 insertions(+), 182 deletions(-) delete mode 100644 src/Core/Services/Home/HomeEntityInterface.php delete mode 100644 src/Core/Services/Home/HomeServiceInterface.php diff --git a/src/Controller/CalendarController.php b/src/Controller/CalendarController.php index 7cec465..671897c 100644 --- a/src/Controller/CalendarController.php +++ b/src/Controller/CalendarController.php @@ -70,8 +70,8 @@ final class CalendarController extends AbstractController $icsContent = $this->calendarExportService->generateIcsContent($days, $entityHistory, $absences); $response = new Response($icsContent); - //$response->headers->set('Content-Type', 'text/calendar; charset=utf-8'); - //$response->headers->set('Content-Disposition', 'attachment; filename="work_calendar.ics"'); + $response->headers->set('Content-Type', 'text/calendar; charset=utf-8'); + $response->headers->set('Content-Disposition', 'attachment; filename="work_calendar.ics"'); return $response; } diff --git a/src/Core/Services/Home/HomeEntityInterface.php b/src/Core/Services/Home/HomeEntityInterface.php deleted file mode 100644 index 0f2873f..0000000 --- a/src/Core/Services/Home/HomeEntityInterface.php +++ /dev/null @@ -1,22 +0,0 @@ -state, ['on', 'home', 'open', 'unlocked', 'active'], true); - } - - public function isOff(): bool - { - return in_array($this->state, ['off', 'away', 'closed', 'locked', 'inactive'], true); - } - public function getDomain(): string { $parts = explode('.', $this->entityId, 2); diff --git a/src/HomeAssistant/HomeAssistantClient.php b/src/HomeAssistant/HomeAssistantClient.php index a79d4e5..0c824e0 100644 --- a/src/HomeAssistant/HomeAssistantClient.php +++ b/src/HomeAssistant/HomeAssistantClient.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace App\HomeAssistant; use DateTimeInterface; -use function explode; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -29,11 +28,6 @@ final readonly class HomeAssistantClient return $this->request('GET', '/api/states'); } - public function getServices(): array - { - return $this->request('GET', '/api/services'); - } - public function getEntityState(string $entityId): array { return $this->request('GET', "/api/states/{$entityId}"); @@ -49,25 +43,6 @@ final readonly class HomeAssistantClient return $this->request('GET', "/api/history/period/{$startDate->format('Y-m-d\TH:i:s\Z')}?{$queryParams}")[0]; } - public function callService(string $domain, string $service, array $data = []): array - { - return $this->request('POST', "/api/services/{$domain}/{$service}", $data); - } - - public function turnOn(string $entityId): array - { - $domain = explode('.', $entityId)[0]; - - return $this->callService($domain, 'turn_on', ['entity_id' => $entityId]); - } - - public function turnOff(string $entityId): array - { - $domain = explode('.', $entityId)[0]; - - return $this->callService($domain, 'turn_off', ['entity_id' => $entityId]); - } - private function request(string $method, string $endpoint, array $data = []): array { $options = [ diff --git a/src/HomeAssistant/HomeAssistantHomeService.php b/src/HomeAssistant/HomeAssistantHomeService.php index 305a42d..89c6a22 100644 --- a/src/HomeAssistant/HomeAssistantHomeService.php +++ b/src/HomeAssistant/HomeAssistantHomeService.php @@ -4,64 +4,13 @@ declare(strict_types=1); namespace App\HomeAssistant; -use App\Core\Services\Home\HomeEntityInterface; -use App\Core\Services\Home\HomeEntityType; -use App\Core\Services\Home\HomeServiceInterface; - -use function array_filter; -use function array_keys; -use function array_map; -use function explode; -use function str_contains; - -final readonly class HomeAssistantHomeService implements HomeServiceInterface +final readonly class HomeAssistantHomeService { public function __construct( private HomeAssistantClient $client, ) { } - public function findEntity(string $entityId): HomeEntityInterface - { - $entityState = $this->getEntityState($entityId); - - return new HomeAssistantEntity($entityState); - } - - public function findAllEntities(): array - { - $states = $this->getAllEntityStates(); - - if (empty($states)) { - throw new HomeAssistantException('No entities found'); - } - - $entities = []; - foreach ($states as $state) { - $type = HomeEntityType::tryFrom($state->getDomain()); - - if ($type === null) { - continue; - } - - $entities[] = new HomeAssistantEntity($state); - } - - return array_filter($entities, fn (HomeEntityInterface $entity) => $entity->getType() === HomeEntityType::LIGHT); - } - - public function callService(string $service, array $data = []): array - { - // Extract domain and service name from the service string - if (str_contains($service, '.')) { - [$domain, $serviceName] = explode('.', $service, 2); - - return $this->client->callService($domain, $serviceName, $data); - } - - throw new HomeAssistantException("Invalid service format. Expected 'domain.service'"); - } - /** * @return EntityState[] */ @@ -81,41 +30,4 @@ final readonly class HomeAssistantHomeService implements HomeServiceInterface return EntityState::fromArray($state); } - - /** - * @return EntityState[] - */ - public function getEntitiesByDomain(string $domain): array - { - $allStates = $this->getAllEntityStates(); - - return array_filter( - $allStates, - static fn (EntityState $state): bool => $state->getDomain() === $domain, - ); - } - - public function turnOn(string $entityId): EntityState - { - $this->client->turnOn($entityId); - - return $this->getEntityState($entityId); - } - - public function turnOff(string $entityId): EntityState - { - $this->client->turnOff($entityId); - - return $this->getEntityState($entityId); - } - - /** - * @return string[] - */ - public function getAvailableDomains(): array - { - $services = $this->client->getServices(); - - return array_keys($services); - } } diff --git a/src/Service/CalendarExportService.php b/src/Service/CalendarExportService.php index 1172772..a4feaee 100644 --- a/src/Service/CalendarExportService.php +++ b/src/Service/CalendarExportService.php @@ -21,6 +21,27 @@ final class CalendarExportService ) { } + /** + * @param array $days + * @param array $entityHistory + * + * @param array $absences + */ public function generateIcsContent(array $days, array $entityHistory, array $absences): string { $icsContent = [ @@ -38,21 +59,16 @@ final class CalendarExportService } $dayDate = clone $day['date']; - $startOfDay = DateTimeImmutable::createFromInterface($dayDate)->setTime(0, 0, 0); - $typicalEndOfDay = DateTimeImmutable::createFromInterface($dayDate)->setTime(17, 30, 0); - - $filteredEntityHistory = array_filter($entityHistory, function (array $state) use ($startOfDay, $typicalEndOfDay) { - return $state['last_changed'] >= $startOfDay && $state['last_changed'] <= $typicalEndOfDay; + + $filteredEntityHistory = array_filter($entityHistory, function (array $state) use ($dayDate) { + return new DateTimeImmutable($state['last_changed']) >= $dayDate->setTime(0, 0, 0) && new DateTimeImmutable($state['last_changed']) <= $dayDate->setTime(23, 59, 59); }); - $startAndEndTimes = $this->getWorkTimesFromHomeAssistant($filteredEntityHistory, $dayDate); + $startAndEndTimes = $this->getWorkTimesFromHomeAssistant($filteredEntityHistory); - if ($startAndEndTimes === null) { - $eventStart = clone $day['date']; - $eventStart->setTime(9, 0, 0); - - $eventEnd = clone $day['date']; - $eventEnd->setTime(17, 30, 0); + if ($startAndEndTimes === null || count($filteredEntityHistory) === 0) { + $eventStart = $dayDate->setTime(9, 0, 0); + $eventEnd = $dayDate->setTime(18, 0, 0); } else { [$eventStart, $eventEnd] = $startAndEndTimes; } @@ -80,17 +96,28 @@ final class CalendarExportService return implode("\r\n", $icsContent); } - private function getWorkTimesFromHomeAssistant(array $stateHistory, DateTimeInterface $date): ?array + /** + * @param array $states + * + * @return array{ + * start: DateTimeImmutable, + * end: DateTimeImmutable + * }|null + */ + private function getWorkTimesFromHomeAssistant(array $states): ?array { try { - - if (empty($stateHistory) || empty($stateHistory[0])) { + if (count($states) === 0) { return null; } + + $states = array_values($states); $startTime = null; $endTime = null; - $states = $stateHistory[0]; foreach ($states as $i => $state) { if ($state['state'] === self::OFFICE_STATE) { diff --git a/src/Service/CalendarService.php b/src/Service/CalendarService.php index cd0021e..85bf804 100644 --- a/src/Service/CalendarService.php +++ b/src/Service/CalendarService.php @@ -7,6 +7,7 @@ use DateTime; use DateTimeImmutable; use DatePeriod; use DateInterval; +use DateTimeInterface; use IntlDateFormatter; final class CalendarService @@ -25,6 +26,19 @@ final class CalendarService ); } + /** + * @param string $startDate + * @param string $endDate + * @return array + */ public function getAllDays(string $startDate, string $endDate): array { $period = new DatePeriod( @@ -37,7 +51,7 @@ final class CalendarService foreach ($period as $date) { $dateObj = DateTimeImmutable::createFromInterface($date); $days[] = [ - 'date' => $date, + 'date' => $dateObj, 'weekday' => (int) $dateObj->format('N'), 'weekdayName' => $this->formatter->format($date), 'weekNumber' => (int) $dateObj->format('W'), @@ -95,7 +109,7 @@ final class CalendarService return false; } - private function isSameDay(DateTime $date1, DateTime $date2): bool + private function isSameDay(DateTimeInterface $date1, DateTimeInterface $date2): bool { return $date1->format('Y-m-d') === $date2->format('Y-m-d'); }