Lines
75.00%
12 / 16
Functions and Methods
60.00%
6 / 10
Classes and Traits
0.00%
0 / 1
| Name | Lines | Functions and Methods | CRAP | Classes and Traits | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| BrokerHaEvents | 75.00% | 12 / 16 | 60.00% | 6 / 10 | 11.56 | 0.00% | 0 / 1 | |||
| __construct | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| stateChanged | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| eventFired | 100.00% | 2 / 2 | 100.00% | 1 / 1 | 1 | |||||
| triggerFired | 0.00% | 0 / 1 | 0.00% | 0 / 1 | 2 | |||||
| triggerRejected | 0.00% | 0 / 1 | 0.00% | 0 / 1 | 2 | |||||
| exposedEntitySynced | 0.00% | 0 / 1 | 0.00% | 0 / 1 | 2 | |||||
| exposedEntityCommanded | 0.00% | 0 / 1 | 0.00% | 0 / 1 | 2 | |||||
| connectionLost | 100.00% | 3 / 3 | 100.00% | 1 / 1 | 1 | |||||
| reconnected | 100.00% | 4 / 4 | 100.00% | 1 / 1 | 1 | |||||
| connectionFailed | 100.00% | 1 / 1 | 100.00% | 1 / 1 | 1 | |||||
| 1 | <?php | |
| 2 | ||
| 3 | declare(strict_types=1); | |
| 4 | ||
| 5 | namespace Stewart\Runtime\Broker; | |
| 6 | ||
| 7 | use Stewart\Contracts\Event\HaEvent; | |
| 8 | use Stewart\Contracts\State\StateChange; | |
| 9 | use Stewart\Contracts\Time\Duration; | |
| 10 | use Stewart\Contracts\Time\Instant; | |
| 11 | use Stewart\Contracts\Trigger\TriggerEvent; | |
| 12 | use Stewart\Runtime\Broker\Exposure\ExposedEntityCommand; | |
| 13 | use Stewart\Runtime\Broker\Exposure\ExposedEntitySync; | |
| 14 | use Stewart\Runtime\Broker\Exposure\ExposureCommandRouter; | |
| 15 | use Stewart\Runtime\Broker\Trigger\TriggerRejections; | |
| 16 | use Stewart\Runtime\Ipc\Message\ExposedEntitySynced; | |
| 17 | use Stewart\Runtime\Ipc\Message\HaConnectionLost; | |
| 18 | use Stewart\Runtime\Ipc\Message\StateResynced; | |
| 19 | use Stewart\Runtime\Model\ResourceScope; | |
| 20 | use Stewart\Support\Wire\TriggerSpec; | |
| 21 | use Throwable; | |
| 22 | ||
| 23 | final readonly class BrokerHaEvents implements HaSessionListener | |
| 24 | { | |
| 25 | public function __construct( | |
| 26 | private HaSession $session, | |
| 27 | private EventRouter $router, | |
| 28 | private WorkerSlotRegistry $slots, | |
| 29 | private ConnectionTracker $connection, | |
| 30 | private BrokerRun $run, | |
| 31 | private TriggerRejections $triggerRejections, | |
| 32 | private RegistryRefresher $registryRefresher, | |
| 33 | private ExposureCommandRouter $commandRouter, | |
| 34 | ) {} | |
| 35 | ||
| 36 | public function stateChanged(StateChange $change): void | |
| 37 | { | |
| 38 | $this->router->broadcastStateChange($change); | |
| 39 | } | |
| 40 | ||
| 41 | public function eventFired(HaEvent $event): void | |
| 42 | { | |
| 43 | $this->registryRefresher->scheduleRefreshFor($event); | |
| 44 | $this->router->routeEvent($event); | |
| 45 | } | |
| 46 | ||
| 47 | public function triggerFired(TriggerSpec $spec, TriggerEvent $event): void | |
| 48 | { | |
| 49 | $this->router->routeTrigger($spec, $event); | |
| 50 | } | |
| 51 | ||
| 52 | public function triggerRejected(TriggerSpec $spec, string $reason): void | |
| 53 | { | |
| 54 | $this->triggerRejections->refuseSubscribers($spec, $reason); | |
| 55 | } | |
| 56 | ||
| 57 | public function exposedEntitySynced(ExposedEntitySync $sync): void | |
| 58 | { | |
| 59 | $this->slots->findHandleForWorker($sync->owner)?->send(new ExposedEntitySynced(ResourceScope::forApp($sync->appId), $sync->key, $sync->snapshot)); | |
| 60 | } | |
| 61 | ||
| 62 | public function exposedEntityCommanded(ExposedEntityCommand $command): void | |
| 63 | { | |
| 64 | $this->commandRouter->routeCommand($command); | |
| 65 | } | |
| 66 | ||
| 67 | public function connectionLost(string $reason, Instant $lostAt): void | |
| 68 | { | |
| 69 | $lost = new HaConnectionLost($lostAt, $reason); | |
| 70 | $this->connection->markReconnecting($lost); | |
| 71 | $this->slots->broadcast($lost); | |
| 72 | } | |
| 73 | ||
| 74 | public function reconnected(Duration $outage): void | |
| 75 | { | |
| 76 | $snapshot = $this->session->snapshotStateCache(); | |
| 77 | $this->connection->markRestored($outage); | |
| 78 | ||
| 79 | // The registry goes first so a resynced change is matched against the current areas and labels. | |
| 80 | $this->slots->broadcast($this->session->snapshotRegistry()->toRegistrySnapshot()); | |
| 81 | $this->slots->broadcast(new StateResynced($snapshot->states, $snapshot->revision, $outage)); | |
| 82 | } | |
| 83 | ||
| 84 | public function connectionFailed(Throwable $error): void | |
| 85 | { | |
| 86 | $this->run->stopWithError('Home Assistant rejected the connection', $error); | |
| 87 | } | |
| 88 | } |