From 77f71672781352055d917d22703dc91c6f551ee9 Mon Sep 17 00:00:00 2001 From: "R. Eric Wheeler" Date: Tue, 21 Nov 2017 18:31:03 -0800 Subject: [PATCH] Added power command --- src/Sikofitt/SamsungTV/Actions/Actions.php | 34 ++++++++++++++----- .../Console/Command/ChannelCommand.php | 24 +++++++++++-- .../Console/Command/InputCommand.php | 2 +- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/Sikofitt/SamsungTV/Actions/Actions.php b/src/Sikofitt/SamsungTV/Actions/Actions.php index fe09089..3fd2707 100644 --- a/src/Sikofitt/SamsungTV/Actions/Actions.php +++ b/src/Sikofitt/SamsungTV/Actions/Actions.php @@ -20,12 +20,12 @@ namespace Sikofitt\SamsungTV\Actions; use React\EventLoop\StreamSelectLoop; -use React\Stream\DuplexResourceStream; -use React\Stream\ReadableResourceStream; -use React\Stream\ThroughStream; use React\Stream\WritableResourceStream; use Sikofitt\SamsungTV\Packet\PacketFactory; +/** + * All available (supported (by me)) TV Keys. + */ class Actions { public const KEY_ENTER = 'KEY_ENTER'; @@ -52,7 +52,8 @@ class Actions public const KEY_AV3 = 'KEY_AV3'; public const KEY_TV = 'KEY_TV'; - + public const KEY_POWEROFF = 'KEY_POWEROFF'; + public static $keyMap = [ '9' => self::KEY_9, '8' => self::KEY_8, @@ -76,9 +77,17 @@ class Actions 'AV1' => self::KEY_AV1, 'AV2' => self::KEY_AV2, 'AV3' => self::KEY_AV3, + 'POWEROFF' => self::KEY_POWEROFF, ]; + /** + * @var \Sikofitt\SamsungTV\Packet\PacketFactory + */ private $packetFactory; + + /** + * @var string + */ private $address; public function __construct(string $tvAddress, int $port = 55000) @@ -101,6 +110,7 @@ class Actions if (array_key_exists(strtoupper($channel), self::$keyMap)) { return base64_encode(self::$keyMap[strtoupper($channel)]); } + @trigger_error(sprintf('Channel "%s" is not yet supported.', $channel)); return ''; } @@ -109,6 +119,7 @@ class Actions { $loop = new StreamSelectLoop(); + // Required for old TVs. The computer presses the buttons too fast. $loop->nextTick(function (): void { usleep(140000); }); @@ -117,20 +128,20 @@ class Actions $stream = new WritableResourceStream($connection, $loop); - - $stream->on('read', function($stream) { - dump($stream); - }); - $stream->write($this->packetFactory->getStartPacket()); $key = $this->transformChannel($keyCode); $stream->write($this->packetFactory->getKeyPacket($key)); + $loop->run(); + $stream->close(); } + /** + * @param string $channel + */ public function changeChannel(string $channel): void { // Add enter at the end of the channel string. @@ -140,6 +151,11 @@ class Actions } } + public function powerOff(): void + { + $this->sendKey('POWEROFF'); + } + /** * @param string $input the source code in self::$keyMap */ diff --git a/src/Sikofitt/SamsungTV/Console/Command/ChannelCommand.php b/src/Sikofitt/SamsungTV/Console/Command/ChannelCommand.php index ce9e433..dd6f953 100644 --- a/src/Sikofitt/SamsungTV/Console/Command/ChannelCommand.php +++ b/src/Sikofitt/SamsungTV/Console/Command/ChannelCommand.php @@ -21,8 +21,10 @@ namespace Sikofitt\SamsungTV\Console\Command; use Sikofitt\SamsungTV\Actions\Actions; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; @@ -44,7 +46,14 @@ class ChannelCommand extends Command 'channel', InputArgument::REQUIRED, 'chanel to change to' - ); + ) + ->addOption( + 'address', + 'a', + InputOption::VALUE_OPTIONAL, + 'The IP address of the tv.' + ) + ; } /** @@ -57,10 +66,19 @@ class ChannelCommand extends Command $io = new SymfonyStyle($input, $output); $channel = $input->getArgument('channel'); + if ((null === $address = $input->getOption('address')) && (false === $address = getenv('SAMSUNG_IP'))) { + throw new InvalidArgumentException('Address is required. You can also set it in the SAMSUNG_IP environment variable.'); + } + //'10.5.4.18'; - $actions = new Actions('10.5.4.18'); + $actions = new Actions($address); + $off = mb_strtolower($channel); - $actions->changeChannel($channel); + if ('off' === $off || 'power' === $off) { + $actions->powerOff(); + } else { + $actions->changeChannel($channel); + } $io->success('Changed the Channel to ' . $channel); } diff --git a/src/Sikofitt/SamsungTV/Console/Command/InputCommand.php b/src/Sikofitt/SamsungTV/Console/Command/InputCommand.php index 9def737..4443cc4 100644 --- a/src/Sikofitt/SamsungTV/Console/Command/InputCommand.php +++ b/src/Sikofitt/SamsungTV/Console/Command/InputCommand.php @@ -65,7 +65,7 @@ class InputCommand extends Command exit; } - if(null === $input->getOption('address')) { + if (null === $input->getOption('address')) { throw new InvalidArgumentException('We need an ip address or host to connect to.'); }