Added power command

This commit is contained in:
R. Eric Wheeler 2017-11-21 18:31:03 -08:00
parent 779a1e53ce
commit 77f7167278
3 changed files with 47 additions and 13 deletions

View File

@ -20,12 +20,12 @@
namespace Sikofitt\SamsungTV\Actions; namespace Sikofitt\SamsungTV\Actions;
use React\EventLoop\StreamSelectLoop; use React\EventLoop\StreamSelectLoop;
use React\Stream\DuplexResourceStream;
use React\Stream\ReadableResourceStream;
use React\Stream\ThroughStream;
use React\Stream\WritableResourceStream; use React\Stream\WritableResourceStream;
use Sikofitt\SamsungTV\Packet\PacketFactory; use Sikofitt\SamsungTV\Packet\PacketFactory;
/**
* All available (supported (by me)) TV Keys.
*/
class Actions class Actions
{ {
public const KEY_ENTER = 'KEY_ENTER'; public const KEY_ENTER = 'KEY_ENTER';
@ -52,6 +52,7 @@ class Actions
public const KEY_AV3 = 'KEY_AV3'; public const KEY_AV3 = 'KEY_AV3';
public const KEY_TV = 'KEY_TV'; public const KEY_TV = 'KEY_TV';
public const KEY_POWEROFF = 'KEY_POWEROFF';
public static $keyMap = [ public static $keyMap = [
'9' => self::KEY_9, '9' => self::KEY_9,
@ -76,9 +77,17 @@ class Actions
'AV1' => self::KEY_AV1, 'AV1' => self::KEY_AV1,
'AV2' => self::KEY_AV2, 'AV2' => self::KEY_AV2,
'AV3' => self::KEY_AV3, 'AV3' => self::KEY_AV3,
'POWEROFF' => self::KEY_POWEROFF,
]; ];
/**
* @var \Sikofitt\SamsungTV\Packet\PacketFactory
*/
private $packetFactory; private $packetFactory;
/**
* @var string
*/
private $address; private $address;
public function __construct(string $tvAddress, int $port = 55000) public function __construct(string $tvAddress, int $port = 55000)
@ -101,6 +110,7 @@ class Actions
if (array_key_exists(strtoupper($channel), self::$keyMap)) { if (array_key_exists(strtoupper($channel), self::$keyMap)) {
return base64_encode(self::$keyMap[strtoupper($channel)]); return base64_encode(self::$keyMap[strtoupper($channel)]);
} }
@trigger_error(sprintf('Channel "%s" is not yet supported.', $channel));
return ''; return '';
} }
@ -109,6 +119,7 @@ class Actions
{ {
$loop = new StreamSelectLoop(); $loop = new StreamSelectLoop();
// Required for old TVs. The computer presses the buttons too fast.
$loop->nextTick(function (): void { $loop->nextTick(function (): void {
usleep(140000); usleep(140000);
}); });
@ -117,20 +128,20 @@ class Actions
$stream = new WritableResourceStream($connection, $loop); $stream = new WritableResourceStream($connection, $loop);
$stream->on('read', function($stream) {
dump($stream);
});
$stream->write($this->packetFactory->getStartPacket()); $stream->write($this->packetFactory->getStartPacket());
$key = $this->transformChannel($keyCode); $key = $this->transformChannel($keyCode);
$stream->write($this->packetFactory->getKeyPacket($key)); $stream->write($this->packetFactory->getKeyPacket($key));
$loop->run(); $loop->run();
$stream->close(); $stream->close();
} }
/**
* @param string $channel
*/
public function changeChannel(string $channel): void public function changeChannel(string $channel): void
{ {
// Add enter at the end of the channel string. // 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 * @param string $input the source code in self::$keyMap
*/ */

View File

@ -21,8 +21,10 @@ namespace Sikofitt\SamsungTV\Console\Command;
use Sikofitt\SamsungTV\Actions\Actions; use Sikofitt\SamsungTV\Actions\Actions;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
@ -44,7 +46,14 @@ class ChannelCommand extends Command
'channel', 'channel',
InputArgument::REQUIRED, InputArgument::REQUIRED,
'chanel to change to' '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); $io = new SymfonyStyle($input, $output);
$channel = $input->getArgument('channel'); $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); $io->success('Changed the Channel to ' . $channel);
} }

View File

@ -65,7 +65,7 @@ class InputCommand extends Command
exit; exit;
} }
if(null === $input->getOption('address')) { if (null === $input->getOption('address')) {
throw new InvalidArgumentException('We need an ip address or host to connect to.'); throw new InvalidArgumentException('We need an ip address or host to connect to.');
} }