Control Samsung TV (>2016) from php

310 Views Asked by At

Hello Everybody I'm trying to make a remote control for my Samsung TV which is a late model (after 2016)

I found this page: https://gist.github.com/hkalina/b70dff4369ff2f0a2afe Unfortunately it does not work and I think that the reason is because it is written for older TVs. I changed the communication port from 55000 to 8001 and the websocket looks to be working but the payload must be wrong. After searching a bit more a found this article http://sc0ty.pl/2012/02/samsung-tv-network-remote-control-protocol/ which describes the comunication protocoll but it also refers to older TVs. I noticed that there are some differences on the packet creation code and I tried to match them but again with no result. I believe that the problem lies to the way the payload packets are created and they have to bee modified, but i don't know how to do it.

I found also a Python script https://github.com/Ape/samsungctl Which works well when executed from the terminal, but doesn't work when I call it from php using shell_exec(). I tried to "decode" the way the packets are created on this script to implement it on the php page but my 0-knowledge on python didn't help.

I host the page on a RaspberryPi(raspbian) connected to the same network as the TV. I would appreciate any help I can get. Thanks a lot.

I attach the final code I end up with.

<form action="remote.php" method="POST">
  <input type="text" name="channel" value="<?php echo htmlspecialchars(@$_POST["channel"]) ?>">
  <input type="submit" name="go" value="Go">
</form>

<form action="remote.php" method="POST">
  <input type="submit" name="key" value="KEY_1">
  <input type="submit" name="key" value="KEY_2">
  <input type="submit" name="key" value="KEY_3"><br>
  <input type="submit" name="key" value="KEY_4">
  <input type="submit" name="key" value="KEY_5">
  <input type="submit" name="key" value="KEY_6"><br>
  <input type="submit" name="key" value="KEY_7">
  <input type="submit" name="key" value="KEY_8">
  <input type="submit" name="key" value="KEY_9"><br>
  <input type="submit" name="key" value="KEY_CHDOWN">
  <input type="submit" name="key" value="KEY_0">
  <input type="submit" name="key" value="KEY_CHUP">
  <br><br>

  <input type="submit" name="key" value="KEY_REC">
  <input type="submit" name="key" value="KEY_STOP"><br>
  <input type="submit" name="key" value="KEY_MUTE">
  <input type="submit" name="key" value="KEY_GUIDE">
  <input type="submit" name="key" value="KEY_MENU">
  <br><br>

  <table>
    <tr><td><input type="submit" name="key" value="KEY_TOOLS"></td>
        <td><input type="submit" name="key" value="KEY_UP"></td><td>
            <input type="submit" name="key" value="KEY_INFO"></td></tr>
    <tr><td><input type="submit" name="key" value="KEY_LEFT"></td>
        <td><input type="submit" name="key" value="KEY_ENTER"></td>
        <td><input type="submit" name="key" value="KEY_RIGHT"></td></tr>
    <tr><td><input type="submit" name="key" value="KEY_RETURN"></td>
        <td><input type="submit" name="key" value="KEY_DOWN"></td>
        <td><input type="submit" name="key" value="KEY_EXIT"></td></tr>
  </table>

</form>


<form action="remote.php" method="POST">
  <input type="text" name="key" value="<?php echo htmlspecialchars(@$_POST["key"]) ?>"><input type="submit" value="OK">
</form>

<pre>
<?php
  if(isset($_POST["go"])) goToChannel($_POST["channel"]);
  if(isset($_POST["key"])) sendkey($_POST["key"]);

  function goToChannel($channel){
    $numbers = str_split(str_pad($channel, 4, "0", STR_PAD_LEFT));
    foreach($numbers as $number){
      sendkey("KEY_".$number);
    }
  }

  function sendkey($key){
    // protocol description: http://sc0ty.pl/2012/02/samsung-tv-network-remote-control-protocol/
    echo $key."\n";
    $address = gethostbyname('192.168.1.157');

    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    if($socket === false) echo "socket_create(): ".socket_strerror(socket_last_error())."\n";

    $result = socket_connect($socket, $address, 8001);
    // ORIGINAL CODE
    //$result = socket_connect($socket, $address, 55000);
    if($result === false) echo "socket_connect(): ".socket_strerror(socket_last_error($socket))."\n";
    
    $packet = 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, 0x14, 0x00, 0x4d, 0x54, 0x6b, 0x79,
                     0x4c, 0x6a, 0x45, 0x32, 0x4f, 0x43, 0x34, 0x78, 0x4c, 0x6a, 0x45, 0x77, 0x4d, 0x41, 0x3d, 0x3d,
                     0x10, 0x00, 0x5a, 0x32, 0x52, 0x7a, 0x4e, 0x7a, 0x4d, 0x30, 0x64, 0x47, 0x64, 0x30, 0x5a, 0x41,
                     0x3d, 0x3d, 0x0c, 0x00, 0x63, 0x32, 0x4d, 0x77, 0x64, 0x48, 0x6b, 0x75, 0x63, 0x47, 0x77, 0x3d);
    
    /* //ORIGINAL CODE 
    $packet = 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);
    */
    
    socket_write($socket, $packet);

    $keycode = base64_encode($key);

    $payload = pack("C*", 0x00, 0x00, 0x00, 0x00).pack("C*",strlen($keycode),0x00).$keycode;

    $packet = 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;
    socket_write($socket, $packet);

    socket_close($socket);
  }
?>
0

There are 0 best solutions below