Skip to content

Commit

Permalink
Refactored async await in discovery (#309)
Browse files Browse the repository at this point in the history
  • Loading branch information
actions-user committed Aug 29, 2024
1 parent d4b3fa1 commit 264ea3d
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 9 deletions.
68 changes: 59 additions & 9 deletions src/Clients/Discovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
use FastyBird\Connector\Viera\Helpers;
use FastyBird\Connector\Viera\Queue;
use FastyBird\Connector\Viera\Services;
use FastyBird\Connector\Viera\ValueObjects;
use FastyBird\Library\Application\Helpers as ApplicationHelpers;
use FastyBird\Library\Metadata\Types as MetadataTypes;
use FastyBird\Module\Devices\Events as DevicesEvents;
use Nette;
use Orisai\ObjectMapper;
use Psr\EventDispatcher as PsrEventDispatcher;
use React\Datagram;
use React\EventLoop;
Expand All @@ -39,6 +41,7 @@
use function preg_match;
use function React\Async\async;
use function React\Async\await;
use function serialize;
use function sprintf;
use function strval;
use function trim;
Expand All @@ -62,10 +65,18 @@ final class Discovery

private const SEARCH_TIMEOUT = 5;

private const PROCESS_RESULTS_TIMER = 0.1;

private const MATCH_DEVICE_LOCATION = '/LOCATION:\s(?<location>[\da-zA-Z:\/.]+)/';

private const MATCH_DEVICE_ID = '/USN:\suuid:(?<usn>[\da-zA-Z-]+)::urn/';

/** @var array<string, ValueObjects\LocalDevice> */
private array $searchResult = [];

/** @var array<string, ValueObjects\LocalDevice> */
private array $processedItems = [];

private EventLoop\TimerInterface|null $handlerTimer = null;

private Datagram\SocketInterface|null $sender = null;
Expand All @@ -78,6 +89,7 @@ public function __construct(
private readonly Viera\Logger $logger,
private readonly Services\MulticastFactory $multicastFactory,
private readonly EventLoop\LoopInterface $eventLoop,
private readonly ObjectMapper\Processing\Processor $objectMapper,
private readonly PsrEventDispatcher\EventDispatcherInterface|null $dispatcher = null,
)
{
Expand Down Expand Up @@ -112,7 +124,7 @@ public function discover(): void
return;
}

$this->sender->on('message', async(function (string $data): void {
$this->sender->on('message', function (string $data): void {
if (preg_match(self::MATCH_DEVICE_LOCATION, $data, $matches) === 1) {
$urlParts = parse_url($matches['location']);

Expand All @@ -121,17 +133,55 @@ public function discover(): void
&& array_key_exists('host', $urlParts)
&& preg_match(self::MATCH_DEVICE_ID, $data, $matches) === 1
) {
try {
$searchResult = $this->objectMapper->process(
[
'id' => $matches['usn'],
'host' => $urlParts['host'],
'port' => array_key_exists(
'port',
$urlParts,
) ? $urlParts['port'] : Entities\Devices\Device::DEFAULT_PORT,
],
ValueObjects\LocalDevice::class,
);

if (!array_key_exists(serialize($searchResult), $this->searchResult)) {
$this->searchResult[serialize($searchResult)] = $searchResult;
}
} catch (Throwable $ex) {
$this->logger->error(
'Received data could not be transformed to message',
[
'source' => MetadataTypes\Sources\Connector::VIERA->value,
'type' => 'discovery-client',
'exception' => ApplicationHelpers\Logger::buildException($ex),
],
);
}
}
}
});

// Processing handler
$this->eventLoop->addPeriodicTimer(
self::PROCESS_RESULTS_TIMER,
async(function (): void {
foreach ($this->searchResult as $item) {
if (array_key_exists(serialize($item), $this->processedItems)) {
continue;
}

$this->processedItems[serialize($item)] = $item;

$this->handleDiscoveredDevice(
$matches['usn'],
$urlParts['host'],
array_key_exists(
'port',
$urlParts,
) ? $urlParts['port'] : Entities\Devices\Device::DEFAULT_PORT,
$item->getId(),
$item->getHost(),
$item->getPort(),
);
}
}
}));
}),
);

// Searching timeout
$this->handlerTimer = $this->eventLoop->addTimer(
Expand Down
2 changes: 2 additions & 0 deletions src/Translations/viera-connector.en_us.neon
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ cmd:
hdmi: "Would you like to configure HDMI inputs?"
nextHdmi: "Would you like to configure another HDMI inputs?"
macAddress: "Would you like to configure television MAC address?"
pairDevice: "Would you like to pair this televisions?"

data:
id: "ID"
Expand Down Expand Up @@ -202,6 +203,7 @@ cmd:
foundDevices: "Found %d new televisions"
noDevicesFound: "No televisions were found"
missingIpAddress: "Something went wrong television: \"%device%\" has not defined its ip address."
foundEncryptedDevices: "Some televisions require to by paired to get encryption keys."
pairing:
started: "Pairing television: \"%device%\"."
finished: "Television: \"%device%\" was successfully paired."
Expand Down
70 changes: 70 additions & 0 deletions src/ValueObjects/LocalDevice.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php declare(strict_types = 1);

/**
* LocalDevice.php
*
* @license More in LICENSE.md
* @copyright https://www.fastybird.com
* @author Adam Kadlec <[email protected]>
* @package FastyBird:VieraConnector!
* @subpackage ValueObjects
* @since 1.0.0
*
* @date 29.08.24
*/

namespace FastyBird\Connector\Viera\ValueObjects;

use Orisai\ObjectMapper;
use function strtolower;

/**
* Local device info
*
* @package FastyBird:VieraConnector!
* @subpackage ValueObjects
*
* @author Adam Kadlec <[email protected]>
*/
final readonly class LocalDevice implements ObjectMapper\MappedObject
{

public function __construct(
#[ObjectMapper\Rules\StringValue(notEmpty: true)]
private string $id,
#[ObjectMapper\Rules\StringValue(notEmpty: true)]
private string $host,
#[ObjectMapper\Rules\IntValue(castNumericString: true)]
private int $port,
)
{
}

public function getId(): string
{
return $this->id;
}

public function getHost(): string
{
return $this->host;
}

public function getPort(): int
{
return $this->port;
}

/**
* @return array<string, string|int>
*/
public function __serialize(): array
{
return [
'id' => $this->getId(),
'host' => strtolower($this->getHost()),
'port' => $this->getPort(),
];
}

}

0 comments on commit 264ea3d

Please sign in to comment.