Initial commit
This commit is contained in:
commit
779a1e53ce
|
@ -0,0 +1,5 @@
|
||||||
|
.php_cs.cache
|
||||||
|
vendor/
|
||||||
|
.idea/
|
||||||
|
composer.lock
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$header = '';
|
||||||
|
|
||||||
|
if(file_exists(__DIR__.'/header.txt')) {
|
||||||
|
$header = file_get_contents('header.txt');
|
||||||
|
}
|
||||||
|
|
||||||
|
return PhpCsFixer\Config::create()
|
||||||
|
->setRiskyAllowed(true)
|
||||||
|
->setRules(
|
||||||
|
[
|
||||||
|
'@PSR2' => true,
|
||||||
|
'@PHP70Migration' => true,
|
||||||
|
'@PHP70Migration:risky' => true,
|
||||||
|
'@PHP71Migration' => true,
|
||||||
|
'@PHP71Migration:risky' => true,
|
||||||
|
'header_comment' => ['header' => $header],
|
||||||
|
'ordered_class_elements' => true,
|
||||||
|
'ordered_imports' => true,
|
||||||
|
'no_mixed_echo_print' => ['use' => 'print'],
|
||||||
|
'strict_param' => true,
|
||||||
|
'strict_comparison' => true,
|
||||||
|
'single_import_per_statement' => false,
|
||||||
|
'phpdoc_order' => true,
|
||||||
|
'array_syntax' => ['syntax' => 'short'],
|
||||||
|
'phpdoc_add_missing_param_annotation' => true,
|
||||||
|
'psr4' => true,
|
||||||
|
'phpdoc_var_without_name' => false,
|
||||||
|
'no_extra_consecutive_blank_lines' => [
|
||||||
|
'break',
|
||||||
|
'continue',
|
||||||
|
'extra',
|
||||||
|
'return',
|
||||||
|
'throw',
|
||||||
|
'parenthesis_brace_block',
|
||||||
|
'square_brace_block',
|
||||||
|
'curly_brace_block',
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)->setFinder(
|
||||||
|
PhpCsFixer\Finder::create()
|
||||||
|
->ignoreDotFiles(true)
|
||||||
|
->ignoreVCS(true)
|
||||||
|
->name('*.php')
|
||||||
|
->in([
|
||||||
|
'src',
|
||||||
|
'tests',
|
||||||
|
])
|
||||||
|
);
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "sikofitt/samsung-tv",
|
||||||
|
"description": "Very simple library to change channels and inputs on old samsung tvs",
|
||||||
|
"type": "library",
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/guzzle": "^6.3",
|
||||||
|
"react/socket-client": "^0.7.0",
|
||||||
|
"guzzlehttp/streams": "^3.0",
|
||||||
|
"symfony/console": "^3.3||^4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^2.7",
|
||||||
|
"squizlabs/php_codesniffer": "^3.1",
|
||||||
|
"phpunit/phpunit": "^6.4",
|
||||||
|
"symfony/var-dumper": "^3.3"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Sikofitt\\SamsungTV\\":"src/Sikofitt/SamsungTV"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "R. Eric Wheeler",
|
||||||
|
"email": "sikofitt@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "stable"
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require __DIR__.'/vendor/autoload.php';
|
||||||
|
\Symfony\Component\Debug\Debug::enable();
|
||||||
|
$app = new \Symfony\Component\Console\Application();
|
||||||
|
|
||||||
|
$app->add(new \Sikofitt\SamsungTV\Console\Command\ChannelCommand());
|
||||||
|
$app->add(new \Sikofitt\SamsungTV\Console\Command\InputCommand());
|
||||||
|
$app->run();
|
|
@ -0,0 +1,14 @@
|
||||||
|
Copyleft (C) 2017 http://sikofitt.com sikofitt@gmail.com
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="PHP_CodeSniffer">
|
||||||
|
<description>The coding standard for PHP_CodeSniffer itself.</description>
|
||||||
|
|
||||||
|
<file>vendor/autoload.php</file>
|
||||||
|
<file>src</file>
|
||||||
|
<file>tests</file>
|
||||||
|
|
||||||
|
<exclude-pattern>*/Standards/*/Tests/*\.(inc|css|js)</exclude-pattern>
|
||||||
|
|
||||||
|
<arg name="basepath" value="."/>
|
||||||
|
<arg name="colors" />
|
||||||
|
<arg name="parallel" value="75" />
|
||||||
|
<arg value="np"/>
|
||||||
|
|
||||||
|
<!-- Don't hide tokenizer exceptions -->
|
||||||
|
<rule ref="Internal.Tokenizer.Exception">
|
||||||
|
<type>error</type>
|
||||||
|
</rule>
|
||||||
|
<rule ref="PSR1">
|
||||||
|
<exclude name="PSR1.Classes.ClassDeclaration" />
|
||||||
|
<type>error</type>
|
||||||
|
</rule>
|
||||||
|
<rule ref="PSR2">
|
||||||
|
<exclude name="PSR2.Namespaces.UseDeclaration" />
|
||||||
|
<exclude name="PSR2.Namespaces.NamespaceDeclaration" />
|
||||||
|
<type>error</type>
|
||||||
|
</rule>
|
||||||
|
<rule ref="Squiz">
|
||||||
|
<exclude name="Squiz" />
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Check var names, but we don't want leading underscores for private vars -->
|
||||||
|
<rule ref="Squiz.NamingConventions.ValidVariableName" />
|
||||||
|
<rule ref="Squiz.NamingConventions.ValidVariableName.PrivateNoUnderscore">
|
||||||
|
<severity>0</severity>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- Have 12 chars padding maximum and always show as errors -->
|
||||||
|
<rule ref="Generic.Formatting.MultipleStatementAlignment">
|
||||||
|
<properties>
|
||||||
|
<property name="maxPadding" value="12"/>
|
||||||
|
<property name="error" value="true"/>
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
</ruleset>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
|
||||||
|
<!--printerClass="PHPUnit_Util_TestDox_ResultPrinter_HTML"-->
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
|
||||||
|
backupGlobals="false"
|
||||||
|
|
||||||
|
colors="true"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
>
|
||||||
|
<php>
|
||||||
|
<ini name="error_reporting" value="-1" />
|
||||||
|
</php>
|
||||||
|
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Project Test Suite">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory>src</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
</phpunit>
|
|
@ -0,0 +1,179 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyleft (C) 2017 http://sikofitt.com sikofitt@gmail.com
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
class Actions
|
||||||
|
{
|
||||||
|
public const KEY_ENTER = 'KEY_ENTER';
|
||||||
|
public const KEY_0 = 'KEY_0';
|
||||||
|
public const KEY_1 = 'KEY_1';
|
||||||
|
public const KEY_2 = 'KEY_2';
|
||||||
|
public const KEY_3 = 'KEY_3';
|
||||||
|
public const KEY_4 = 'KEY_4';
|
||||||
|
public const KEY_5 = 'KEY_5';
|
||||||
|
public const KEY_6 = 'KEY_6';
|
||||||
|
public const KEY_7 = 'KEY_7';
|
||||||
|
public const KEY_8 = 'KEY_8';
|
||||||
|
public const KEY_9 = 'KEY_9';
|
||||||
|
public const KEY_PLUS100 = 'KEY_PLUS100'; // - key
|
||||||
|
|
||||||
|
public const KEY_HDMI = 'KEY_HDMI'; // Apparently not
|
||||||
|
public const KEY_HDMI1 = 'KEY_HDMI1'; // the same
|
||||||
|
public const KEY_HDMI2 = 'KEY_HDMI2';
|
||||||
|
public const KEY_HDMI3 = 'KEY_HDMI3';
|
||||||
|
public const KEY_HDMI4 = 'KEY_HDMI4';
|
||||||
|
|
||||||
|
public const KEY_AV1 = 'KEY_AV1';
|
||||||
|
public const KEY_AV2 = 'KEY_AV2';
|
||||||
|
public const KEY_AV3 = 'KEY_AV3';
|
||||||
|
|
||||||
|
public const KEY_TV = 'KEY_TV';
|
||||||
|
|
||||||
|
public static $keyMap = [
|
||||||
|
'9' => self::KEY_9,
|
||||||
|
'8' => self::KEY_8,
|
||||||
|
'7' => self::KEY_7,
|
||||||
|
'6' => self::KEY_6,
|
||||||
|
'5' => self::KEY_5,
|
||||||
|
'4' => self::KEY_4,
|
||||||
|
'3' => self::KEY_3,
|
||||||
|
'2' => self::KEY_2,
|
||||||
|
'1' => self::KEY_1,
|
||||||
|
'0' => self::KEY_0,
|
||||||
|
'-' => self::KEY_PLUS100,
|
||||||
|
'.' => self::KEY_PLUS100,
|
||||||
|
'E' => self::KEY_ENTER,
|
||||||
|
'H' => self::KEY_HDMI,
|
||||||
|
'H1' => self::KEY_HDMI1,
|
||||||
|
'H2' => self::KEY_HDMI2,
|
||||||
|
'H3' => self::KEY_HDMI3,
|
||||||
|
'H4' => self::KEY_HDMI4,
|
||||||
|
'T' => self::KEY_TV,
|
||||||
|
'AV1' => self::KEY_AV1,
|
||||||
|
'AV2' => self::KEY_AV2,
|
||||||
|
'AV3' => self::KEY_AV3,
|
||||||
|
];
|
||||||
|
|
||||||
|
private $packetFactory;
|
||||||
|
private $address;
|
||||||
|
|
||||||
|
public function __construct(string $tvAddress, int $port = 55000)
|
||||||
|
{
|
||||||
|
$this->packetFactory = new PacketFactory();
|
||||||
|
$this->address = sprintf('%s:%d', $tvAddress, $port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function transformChannels(string $channel): \Generator
|
||||||
|
{
|
||||||
|
$codes = str_split($channel);
|
||||||
|
|
||||||
|
foreach ($codes as $code) {
|
||||||
|
yield $this->transformChannel($code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function transformChannel(string $channel): string
|
||||||
|
{
|
||||||
|
if (array_key_exists(strtoupper($channel), self::$keyMap)) {
|
||||||
|
return base64_encode(self::$keyMap[strtoupper($channel)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendKey(string $keyCode): void
|
||||||
|
{
|
||||||
|
$loop = new StreamSelectLoop();
|
||||||
|
|
||||||
|
$loop->nextTick(function (): void {
|
||||||
|
usleep(140000);
|
||||||
|
});
|
||||||
|
|
||||||
|
$connection = stream_socket_client($this->address);
|
||||||
|
|
||||||
|
$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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function changeChannel(string $channel): void
|
||||||
|
{
|
||||||
|
// Add enter at the end of the channel string.
|
||||||
|
$channelArr = str_split($channel.'E');
|
||||||
|
foreach ($channelArr as $item) {
|
||||||
|
$this->sendKey($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $input the source code in self::$keyMap
|
||||||
|
*/
|
||||||
|
public function changeInput(string $input): void
|
||||||
|
{
|
||||||
|
switch (strtoupper($input)) {
|
||||||
|
default:
|
||||||
|
case 'TV':
|
||||||
|
$this->sendKey('T');
|
||||||
|
break;
|
||||||
|
case 'HDMI':
|
||||||
|
$this->sendKey('H');
|
||||||
|
break;
|
||||||
|
case 'HDMI1':
|
||||||
|
$this->sendKey('H1');
|
||||||
|
break;
|
||||||
|
case 'HDMI2':
|
||||||
|
$this->sendKey('H2');
|
||||||
|
break;
|
||||||
|
case 'HDMI3':
|
||||||
|
$this->sendKey('H3');
|
||||||
|
break;
|
||||||
|
case 'HDMI4':
|
||||||
|
$this->sendKey('H4');
|
||||||
|
break;
|
||||||
|
case 'AV1':
|
||||||
|
$this->sendKey('AV1');
|
||||||
|
break;
|
||||||
|
case 'AV2':
|
||||||
|
$this->sendKey('AV2');
|
||||||
|
break;
|
||||||
|
case 'AV3':
|
||||||
|
$this->sendKey('AV3');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyleft (C) 2017 http://sikofitt.com sikofitt@gmail.com
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Sikofitt\SamsungTV\Console\Command;
|
||||||
|
|
||||||
|
use Sikofitt\SamsungTV\Actions\Actions;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to change channels
|
||||||
|
*/
|
||||||
|
class ChannelCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function configure(): void
|
||||||
|
{
|
||||||
|
$this->setName('channel')
|
||||||
|
->setDescription('change the channel')
|
||||||
|
->addArgument(
|
||||||
|
'channel',
|
||||||
|
InputArgument::REQUIRED,
|
||||||
|
'chanel to change to'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): void
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
|
||||||
|
$channel = $input->getArgument('channel');
|
||||||
|
|
||||||
|
$actions = new Actions('10.5.4.18');
|
||||||
|
|
||||||
|
$actions->changeChannel($channel);
|
||||||
|
|
||||||
|
$io->success('Changed the Channel to ' . $channel);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyleft (C) 2017 http://sikofitt.com sikofitt@gmail.com
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command to change the input of the Samsung TV.
|
||||||
|
*/
|
||||||
|
class InputCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function configure(): void
|
||||||
|
{
|
||||||
|
$this->setName('input')
|
||||||
|
->setDescription('Change the TV source')
|
||||||
|
->addOption('port', 'p', InputOption::VALUE_REQUIRED, 'Port of the Samsung TV', 55000)
|
||||||
|
->addOption('address', 'a', InputOption::VALUE_REQUIRED, 'IP or Host of the SamsungTV')
|
||||||
|
->addArgument(
|
||||||
|
'input',
|
||||||
|
InputArgument::REQUIRED,
|
||||||
|
'The input channel. For a list type \'list\'.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function interact(InputInterface $input, OutputInterface $output): void
|
||||||
|
{
|
||||||
|
$inputArg = $input->getArgument('input');
|
||||||
|
|
||||||
|
if ('list' === strtolower($inputArg)) {
|
||||||
|
$output->writeln(sprintf('Available inputs are : %s.%s', implode(', ', $this->getAvailableInputs()), PHP_EOL));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(null === $input->getOption('address')) {
|
||||||
|
throw new InvalidArgumentException('We need an ip address or host to connect to.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === in_array(strtolower($inputArg), $this->getAvailableInputs(), true)) {
|
||||||
|
throw new InvalidArgumentException('Input ' . $inputArg . ' is not available');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @throws \Symfony\Component\Console\Exception\InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return null|int
|
||||||
|
*/
|
||||||
|
public function execute(InputInterface $input, OutputInterface $output): ?int
|
||||||
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$inputArg = $input->getArgument('input');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$actions = new Actions($input->getOption('address'), $input->getOption('port'));
|
||||||
|
$actions->changeInput(strtoupper($inputArg));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$io->error($e->getMessage());
|
||||||
|
return 1;
|
||||||
|
} finally {
|
||||||
|
$io->success('Changed source input to ' . $inputArg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getAvailableInputs(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tv',
|
||||||
|
'hdmi',
|
||||||
|
'hdmi1', // different than hdmi for some reason.
|
||||||
|
'hdmi2',
|
||||||
|
'hdmi3',
|
||||||
|
'hdmi4',
|
||||||
|
'av1',
|
||||||
|
'av2',
|
||||||
|
'av3',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,166 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyleft (C) 2017 http://sikofitt.com sikofitt@gmail.com
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Sikofitt\SamsungTV\Packet;
|
||||||
|
|
||||||
|
class PacketFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @link https://gist.github.com/honza889/b70dff4369ff2f0a2afe#file-remote-php-L63
|
||||||
|
*
|
||||||
|
* @return string The Start command
|
||||||
|
*/
|
||||||
|
public function getStartPacket(): string
|
||||||
|
{
|
||||||
|
return pack(
|
||||||
|
'C*',
|
||||||
|
0x00,
|
||||||
|
0x13,
|
||||||
|
0x00,
|
||||||
|
0x69,
|
||||||
|
0x70,
|
||||||
|
0x68,
|
||||||
|
0x6f,
|
||||||
|
0x6e,
|
||||||
|
0x65,
|
||||||
|
0x2e,
|
||||||
|
0x69,
|
||||||
|
0x61,
|
||||||
|
0x70,
|
||||||
|
0x70,
|
||||||
|
0x2e,
|
||||||
|
0x73,
|
||||||
|
0x61,
|
||||||
|
0x6d,
|
||||||
|
0x73,
|
||||||
|
0x75,
|
||||||
|
0x6e,
|
||||||
|
0x67,
|
||||||
|
0x38,
|
||||||
|
0x00,
|
||||||
|
0x64,
|
||||||
|
0x00,
|
||||||
|
0x10,
|
||||||
|
0x00,
|
||||||
|
0x4d,
|
||||||
|
0x54,
|
||||||
|
0x41,
|
||||||
|
0x75,
|
||||||
|
0x4d,
|
||||||
|
0x43,
|
||||||
|
0x34,
|
||||||
|
0x77,
|
||||||
|
0x4c,
|
||||||
|
0x6a,
|
||||||
|
0x49,
|
||||||
|
0x79,
|
||||||
|
0x4d,
|
||||||
|
0x67,
|
||||||
|
0x3d,
|
||||||
|
0x3d,
|
||||||
|
0x14,
|
||||||
|
0x00,
|
||||||
|
0x63,
|
||||||
|
0x6d,
|
||||||
|
0x46,
|
||||||
|
0x75,
|
||||||
|
0x5a,
|
||||||
|
0x47,
|
||||||
|
0x39,
|
||||||
|
0x74,
|
||||||
|
0x55,
|
||||||
|
0x6d,
|
||||||
|
0x56,
|
||||||
|
0x74,
|
||||||
|
0x62,
|
||||||
|
0x33,
|
||||||
|
0x52,
|
||||||
|
0x6c,
|
||||||
|
0x53,
|
||||||
|
0x55,
|
||||||
|
0x51,
|
||||||
|
0x3d,
|
||||||
|
0x0c,
|
||||||
|
0x00,
|
||||||
|
0x62,
|
||||||
|
0x58,
|
||||||
|
0x6c,
|
||||||
|
0x53,
|
||||||
|
0x5a,
|
||||||
|
0x57,
|
||||||
|
0x31,
|
||||||
|
0x76,
|
||||||
|
0x64,
|
||||||
|
0x47,
|
||||||
|
0x55,
|
||||||
|
0x3d
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://gist.github.com/honza889/b70dff4369ff2f0a2afe#file-remote-php-L73
|
||||||
|
*
|
||||||
|
* @param string $keyCode the base64 encoded key code.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPayload(string $keyCode): string
|
||||||
|
{
|
||||||
|
return pack("C*", 0x00, 0x00, 0x00, 0x00).pack("C*", strlen($keyCode), 0x00).$keyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link https://gist.github.com/honza889/b70dff4369ff2f0a2afe#file-remote-php-L75-L76
|
||||||
|
*
|
||||||
|
* @param string $keyCode the base64 encoded key code.
|
||||||
|
*
|
||||||
|
* @return string The final payload to send to the TV.
|
||||||
|
*/
|
||||||
|
public function getKeyPacket(string $keyCode): string
|
||||||
|
{
|
||||||
|
$payload = $this->getPayload($keyCode);
|
||||||
|
|
||||||
|
return pack(
|
||||||
|
"C*",
|
||||||
|
0x00,
|
||||||
|
0x13,
|
||||||
|
0x00,
|
||||||
|
0x69,
|
||||||
|
0x70,
|
||||||
|
0x68,
|
||||||
|
0x6f,
|
||||||
|
0x6e,
|
||||||
|
0x65,
|
||||||
|
0x2e,
|
||||||
|
0x69,
|
||||||
|
0x61,
|
||||||
|
0x70,
|
||||||
|
0x70,
|
||||||
|
0x2e,
|
||||||
|
0x73,
|
||||||
|
0x61,
|
||||||
|
0x6d,
|
||||||
|
0x73,
|
||||||
|
0x75,
|
||||||
|
0x6e,
|
||||||
|
0x67
|
||||||
|
) .
|
||||||
|
pack("C*", strlen($payload)-1).$payload;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue