Skip to content

Commit

Permalink
[viera-connector-homekit-connector-bridge] Prepared viera connector t…
Browse files Browse the repository at this point in the history
…o homekit connector bridge (#306)
  • Loading branch information
actions-user committed Sep 29, 2024
1 parent cc300ec commit 53798a8
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 126 deletions.
8 changes: 5 additions & 3 deletions src/Commands/Execute.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ protected function configure(): void
'connector',
'c',
Input\InputOption::VALUE_OPTIONAL,
'Run devices module connector',
'Connector ID or identifier',
true,

Check warning on line 78 in src/Commands/Execute.php

View workflow job for this annotation

GitHub Actions / PHP Tests For Mutants (8.2, ubuntu-latest) / Mutation Tests (PHP 8.2)

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ */ protected function configure() : void { - $this->setName(self::NAME)->setDescription('Zigbee2MQTT connector service')->setDefinition(new Input\InputDefinition([new Input\InputOption('connector', 'c', Input\InputOption::VALUE_OPTIONAL, 'Connector ID or identifier', true)])); + $this->setName(self::NAME)->setDescription('Zigbee2MQTT connector service')->setDefinition(new Input\InputDefinition([new Input\InputOption('connector', 'c', Input\InputOption::VALUE_OPTIONAL, 'Connector ID or identifier', false)])); } /** * @throws Console\Exception\ExceptionInterface
),
]),
Expand All @@ -100,9 +100,11 @@ protected function execute(Input\InputInterface $input, Output\OutputInterface $

$io = new Style\SymfonyStyle($input, $output);

$io->title((string) $this->translator->translate('//zigbee2mqtt-connector.cmd.execute.title'));
if ($input->getOption('quiet') === false) {
$io->title((string) $this->translator->translate('//zigbee2mqtt-connector.cmd.execute.title'));

$io->note((string) $this->translator->translate('//zigbee2mqtt-connector.cmd.execute.subtitle'));
$io->note((string) $this->translator->translate('//zigbee2mqtt-connector.cmd.execute.subtitle'));
}

if ($input->getOption('no-interaction') === false) {
$question = new Console\Question\ConfirmationQuestion(
Expand Down
8 changes: 7 additions & 1 deletion src/DI/Zigbee2MqttExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,18 @@ public function loadConfiguration(): void
$builder->addFactoryDefinition($this->prefix('writers.event'))
->setImplement(Writers\EventFactory::class)
->getResultDefinition()
->setType(Writers\Event::class);
->setType(Writers\Event::class)
->setArguments([
'logger' => $logger,
]);

$builder->addFactoryDefinition($this->prefix('writers.exchange'))
->setImplement(Writers\ExchangeFactory::class)
->getResultDefinition()
->setType(Writers\Exchange::class)
->setArguments([
'logger' => $logger,
])
->addTag(ExchangeDI\ExchangeExtension::CONSUMER_STATE, false);

/**
Expand Down
28 changes: 28 additions & 0 deletions src/Queue/Consumers/WriteSubDeviceChannelPropertyState.php
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,34 @@ public function consume(Queue\Messages\Message $message): bool
return true;
}

if (!$this->getClient($connector)->isConnected()) {
$this->logger->error(
'Client is not connected to Zigbee2MQTT',
[
'source' => MetadataTypes\Sources\Connector::ZIGBEE2MQTT->value,
'type' => 'write-sub-device-channel-property-state-message-consumer',
'connector' => [
'id' => $connector->getId()->toString(),
],
'bridge' => [
'id' => $bridge->getId()->toString(),
],
'device' => [
'id' => $device->getId()->toString(),
],
'channel' => [
'id' => $channel->getId()->toString(),
],
'property' => [
'id' => $message->getProperty()->toString(),
],
'data' => $message->toArray(),
],
);

return false;
}

try {
$this->getClient($connector)
->publish(
Expand Down
2 changes: 1 addition & 1 deletion src/Queue/Messages/WriteSubDeviceChannelPropertyState.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function __construct(
new ObjectMapper\Rules\MappedObjectValue(class: State::class),
new ObjectMapper\Rules\NullValue(),
])]
private State|null $state,
private State|null $state = null,
)
{
}
Expand Down
104 changes: 57 additions & 47 deletions src/Writers/Event.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@
namespace FastyBird\Connector\Zigbee2Mqtt\Writers;

use FastyBird\Connector\Zigbee2Mqtt\Documents;
use FastyBird\Connector\Zigbee2Mqtt\Exceptions;
use FastyBird\Connector\Zigbee2Mqtt\Queries;
use FastyBird\Connector\Zigbee2Mqtt\Queue;
use FastyBird\Library\Application\Helpers as ApplicationHelpers;
use FastyBird\Library\Metadata\Types as MetadataTypes;
use FastyBird\Module\Devices\Events as DevicesEvents;
use FastyBird\Module\Devices\Exceptions as DevicesExceptions;
use Symfony\Component\EventDispatcher;
use Throwable;

/**
* Event based properties writer
Expand All @@ -44,57 +45,66 @@ public static function getSubscribedEvents(): array
];
}

/**
* @throws DevicesExceptions\InvalidState
* @throws Exceptions\Runtime
*/
public function stateChanged(
DevicesEvents\ChannelPropertyStateEntityCreated|DevicesEvents\ChannelPropertyStateEntityUpdated $event,
): void
{
$state = $event->getGet();

if ($state->getExpectedValue() === null || $state->getPending() !== true) {
return;
}

$findChannelQuery = new Queries\Configuration\FindChannels();
$findChannelQuery->byId($event->getProperty()->getChannel());

$channel = $this->channelsConfigurationRepository->findOneBy(
$findChannelQuery,
Documents\Channels\Channel::class,
);

if ($channel === null) {
return;
}

$findDeviceQuery = new Queries\Configuration\FindSubDevices();
$findDeviceQuery->forConnector($this->connector);
$findDeviceQuery->byId($channel->getDevice());

$device = $this->devicesConfigurationRepository->findOneBy(
$findDeviceQuery,
Documents\Devices\SubDevice::class,
);

if ($device === null) {
return;
}

$this->queue->append(
$this->messageBuilder->create(
Queue\Messages\WriteSubDeviceChannelPropertyState::class,
try {
$state = $event->getGet();

if ($state->getExpectedValue() === null || $state->getPending() !== true) {
return;
}

$findChannelQuery = new Queries\Configuration\FindChannels();
$findChannelQuery->byId($event->getProperty()->getChannel());

$channel = $this->channelsConfigurationRepository->findOneBy(
$findChannelQuery,
Documents\Channels\Channel::class,
);

if ($channel === null) {
return;
}

$findDeviceQuery = new Queries\Configuration\FindSubDevices();
$findDeviceQuery->forConnector($this->connector);
$findDeviceQuery->byId($channel->getDevice());

$device = $this->devicesConfigurationRepository->findOneBy(
$findDeviceQuery,
Documents\Devices\SubDevice::class,
);

if ($device === null) {
return;
}

$this->queue->append(
$this->messageBuilder->create(
Queue\Messages\WriteSubDeviceChannelPropertyState::class,
[
'connector' => $this->connector->getId(),
'device' => $device->getId(),
'channel' => $channel->getId(),
'property' => $event->getProperty()->getId(),
'state' => $event->getGet()->toArray(),
],
),
);

} catch (Throwable $ex) {
// Log caught exception
$this->logger->error(
'Characteristic value could not be prepared for writing',
[
'connector' => $this->connector->getId(),
'device' => $device->getId(),
'channel' => $channel->getId(),
'property' => $event->getProperty()->getId(),
'state' => $event->getGet()->toArray(),
'source' => MetadataTypes\Sources\Connector::ZIGBEE2MQTT->value,
'type' => 'event-writer',
'exception' => ApplicationHelpers\Logger::buildException($ex),
],
),
);
);
}
}

}
127 changes: 73 additions & 54 deletions src/Writers/Exchange.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,28 @@

namespace FastyBird\Connector\Zigbee2Mqtt\Writers;

use FastyBird\Connector\Zigbee2Mqtt;
use FastyBird\Connector\Zigbee2Mqtt\Documents;
use FastyBird\Connector\Zigbee2Mqtt\Exceptions;
use FastyBird\Connector\Zigbee2Mqtt\Helpers;
use FastyBird\Connector\Zigbee2Mqtt\Queries;
use FastyBird\Connector\Zigbee2Mqtt\Queue;
use FastyBird\DateTimeFactory;
use FastyBird\Library\Application\Helpers as ApplicationHelpers;
use FastyBird\Library\Exchange\Consumers as ExchangeConsumers;
use FastyBird\Library\Exchange\Exceptions as ExchangeExceptions;
use FastyBird\Library\Metadata\Documents as MetadataDocuments;
use FastyBird\Library\Metadata\Exceptions as MetadataExceptions;
use FastyBird\Library\Metadata\Types as MetadataTypes;
use FastyBird\Library\Tools\Exceptions as ToolsExceptions;
use FastyBird\Module\Devices\Constants as DevicesConstants;
use FastyBird\Module\Devices\Documents as DevicesDocuments;
use FastyBird\Module\Devices\Exceptions as DevicesExceptions;
use FastyBird\Module\Devices\Models as DevicesModels;
use React\EventLoop;
use Throwable;
use function array_merge;
use function str_starts_with;

/**
* Exchange based properties writer
Expand All @@ -50,6 +55,7 @@ public function __construct(
Documents\Connectors\Connector $connector,
Helpers\MessageBuilder $messageBuilder,
Queue\Queue $queue,
Zigbee2Mqtt\Logger $logger,
DevicesModels\Configuration\Devices\Repository $devicesConfigurationRepository,
DevicesModels\Configuration\Channels\Repository $channelsConfigurationRepository,
DevicesModels\Configuration\Channels\Properties\Repository $channelsPropertiesConfigurationRepository,
Expand All @@ -63,6 +69,7 @@ public function __construct(
$connector,
$messageBuilder,
$queue,
$logger,
$devicesConfigurationRepository,
$channelsConfigurationRepository,
$channelsPropertiesConfigurationRepository,
Expand Down Expand Up @@ -101,67 +108,79 @@ public function disconnect(): void
$this->consumer->disable(self::class);
}

/**
* @throws DevicesExceptions\InvalidState
* @throws Exceptions\Runtime
*/
public function consume(
MetadataTypes\Sources\Source $source,
string $routingKey,
MetadataDocuments\Document|null $document,
): void
{
if ($document instanceof DevicesDocuments\States\Channels\Properties\Property) {
if (
$document->getGet()->getExpectedValue() === null
|| $document->getPending() !== true
) {
return;
try {
if ($document instanceof DevicesDocuments\States\Channels\Properties\Property) {
if (str_starts_with($routingKey, DevicesConstants::MESSAGE_BUS_DELETED_ROUTING_KEY)) {
return;
}

if (
$document->getGet()->getExpectedValue() === null
|| $document->getPending() !== true
) {
return;
}

$findChannelQuery = new Queries\Configuration\FindChannels();
$findChannelQuery->byId($document->getChannel());

$channel = $this->channelsConfigurationRepository->findOneBy(
$findChannelQuery,
Documents\Channels\Channel::class,
);

if ($channel === null) {
return;
}

$findDeviceQuery = new Queries\Configuration\FindSubDevices();
$findDeviceQuery->forConnector($this->connector);
$findDeviceQuery->byId($channel->getDevice());

$device = $this->devicesConfigurationRepository->findOneBy(
$findDeviceQuery,
Documents\Devices\SubDevice::class,
);

if ($device === null) {
return;
}

$this->queue->append(
$this->messageBuilder->create(
Queue\Messages\WriteSubDeviceChannelPropertyState::class,
[
'connector' => $this->connector->getId(),
'device' => $device->getId(),
'channel' => $channel->getId(),
'property' => $document->getId(),
'state' => array_merge(
$document->getGet()->toArray(),
[
'id' => $document->getId(),
'valid' => $document->isValid(),
'pending' => $document->getPending(),
],
),
],
),
);
}

$findChannelQuery = new Queries\Configuration\FindChannels();
$findChannelQuery->byId($document->getChannel());

$channel = $this->channelsConfigurationRepository->findOneBy(
$findChannelQuery,
Documents\Channels\Channel::class,
);

if ($channel === null) {
return;
}

$findDeviceQuery = new Queries\Configuration\FindSubDevices();
$findDeviceQuery->forConnector($this->connector);
$findDeviceQuery->byId($channel->getDevice());

$device = $this->devicesConfigurationRepository->findOneBy(
$findDeviceQuery,
Documents\Devices\SubDevice::class,
);

if ($device === null) {
return;
}

$this->queue->append(
$this->messageBuilder->create(
Queue\Messages\WriteSubDeviceChannelPropertyState::class,
[
'connector' => $this->connector->getId(),
'device' => $device->getId(),
'channel' => $channel->getId(),
'property' => $document->getId(),
'state' => array_merge(
$document->getGet()->toArray(),
[
'id' => $document->getId(),
'valid' => $document->isValid(),
'pending' => $document->getPending(),
],
),
],
),
} catch (Throwable $ex) {
// Log caught exception
$this->logger->error(
'Characteristic value could not be prepared for writing',
[
'source' => MetadataTypes\Sources\Connector::ZIGBEE2MQTT->value,
'type' => 'exchange-writer',
'exception' => ApplicationHelpers\Logger::buildException($ex),
],
);
}
}
Expand Down
Loading

0 comments on commit 53798a8

Please sign in to comment.