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