LG TV steuern/abfragen?

Ich bekomme neuerdings ähnliche Meldungen:

22.07.2023, 23:20:29 | ScriptEngine         | Result for Event 26209
 
Warning: fsockopen(): Unable to connect to 192.168.1.60:3000 (Connection timed out) in /var/lib/symcon/scripts/17551.ips.php on line 26

Fatal error: Uncaught TypeError: socket_set_timeout(): Argument #1 ($stream) must be of type resource, bool given in /var/lib/symcon/scripts/17551.ips.php:27
Stack trace:
#0 /var/lib/symcon/scripts/17551.ips.php(27): socket_set_timeout(false, 0, 10000)
#1 /var/lib/symcon/scripts/17551.ips.php(50): webOSTV->connect()
#2 /var/lib/symcon/scripts/29142.ips.php(6): webOSTV->lg_handshake()
#3 {main}
  thrown in /var/lib/symcon/scripts/17551.ips.php on line 27

Da habe ich auch Hilfe nötig.

Meine Lösung läuft auch nicht mehr, wir haben allerdings mittlerweile auch ein neueres Modell.
So wie es aussieht hat LG die Art Verbindung geändert.
Vorher lief es über einen normalen Websocket (ws://…:3000), jetzt ist es wss://…:3001 über TLS.

Ich kann die Verbindung über den Websocket herstellen, aber mehr nicht … bzw. ich weiß nicht wie ich den Handshakebefehl auslösen kann. Ein Zertifikat kann man über die Developerseite von LG bekommen.
Bei FHEM, HA und einigen anderen Lösungen läufts scheinbar.
Evtl. kann ja jemand mit der Info mehr anfangen :wink:

Hier gibt es eine Lösung mit Python : GitHub - klattimer/LGWebOSRemote: Command line webOS remote for LGTVs

Hat hier wirklich niemand eine der neueren Generationen an IPS angebunden ? :woozy_face:

Edit: Hier gibts scheinbar auch noch ne Lösung …

Anscheinend haben nicht sehr viele einen LG TV…

Bei mir geht es auch nicht mehr.

Fehlermeldung:
Sending WS handshake
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: W0ElfVJFM0tUMVR1RXVoUQ==
Host: 192.168.0.209:3000

ERROR during WS handshake!
Sending WS handshake
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: W0ElfVJFM0tUMVR1RXVoUQ==
Host: 192.168.0.209:3000

TV hat ein Update installiert.

Hat wer eine Idee?

HI ich habe 2 IPS Instancen am laufen, unter 6.4 geht es noch einwandfrei unter 7.x geht es nicht mehr…

ich wurde mal behaupten, das es an Symcon liegt, das da was fehlerhaft fsockopen portiert wurde oder es wurde was an php upgedatet, das fsockopen nicht mehr so von api her funktioniert :frowning:

Hallo,
kann sich denn bitte mal einer der Experten dazu äußern?
Vielleicht ist es nicht so aufwändig den Fehler abzufangen.
Wo und an welcher Stelle kann man ggf. noch mit weiteren Informationen helfen?
Gruß
Marc

1 „Gefällt mir“

Ich hole das hier mal hoch.

Kann hier bitte jemand helfen.

Gruß
Rudi

1 „Gefällt mir“

Ich habe den Grund für meine Fehlermeldungen gefunden. In dem Skript webos.inc.php ist recht am Anfang ein Fehler:

$ws_handshake_cmd.= "Sec-WebSocket-Key: " . $this->ws_key . "\r\n";

Hinter ws_key ist ein Leerzeichen, bevor der Punkt kommt. Ich habe das Leerzeichen gelöscht und nun kommen auch keine fatal error Meldungen mehr.

So ist es richtig.

$ws_handshake_cmd.= "Sec-WebSocket-Key: " . $this->ws_key. "\r\n";

@froema Könntest Du noch einmal alles an Scripts posten? Es ist definitiv leichter für mich ( und andere ) es zum laufen zu bekommen, als sich vorher 150 Post durchzulesen, wovon der Erste von 2016 ist.
Ich habe den 2021 G1 OLED und würde es gerne mal ausprobieren.

Danke,
Peter

Hi Peter,
ich bin da absolut kein Experte. Ich weiß ehrlich gesagt auch nicht, wie alt mein LG ist.
Ich kann’s aber versuchen.
Als Erstes legst du folgendes Skript an:

<?php


class webOSTV
{
    private $host, $port, $ws_key, $path, $lg_key, $sock, $connected=false, $handshaked=false;

    function __construct($host, $port=3000, $lgKey="NOKEY", $path="/")
    {
        $this->host = $host;
        $this->port = $port;
        $this->lg_key = $lgKey;
        $this->path = $path;
        $this->ws_key = $key = base64_encode(generateRandomString(16, false, true));
        if ($this->lg_key=="NOKEY") unset($this->lg_key);    
    }
        
    function connect()
    {
        $ws_handshake_cmd = "GET " . $this->path . " HTTP/1.1\r\n";
        $ws_handshake_cmd.= "Upgrade: websocket\r\n";
        $ws_handshake_cmd.= "Connection: Upgrade\r\n";
        $ws_handshake_cmd.= "Sec-WebSocket-Version: 13\r\n";            
        $ws_handshake_cmd.= "Sec-WebSocket-Key: " . $this->ws_key. "\r\n";
        $ws_handshake_cmd.= "Host: ".$this->host.":".$this->port."\r\n\r\n";
        $this->sock = fsockopen($this->host, $this->port, $errno, $errstr, 2);
        socket_set_timeout($this->sock, 0, 10000);
        echo     "Sending WS handshake\n$ws_handshake_cmd\n";
        $response = $this->send($ws_handshake_cmd);
        if ($response)
        {
            echo "WS Handshake Response:\n$response\n";
        } 
        else 
        echo "ERROR during WS handshake!\n";
        preg_match('#Sec-WebSocket-Accept:\s(.*)$#mU', $response, $matches);
        if ($matches) 
            {
            $keyAccept = trim($matches[1]);
            $expectedResonse = base64_encode(pack('H*', sha1($this->ws_key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
            $this->connected = ($keyAccept === $expectedResonse) ? true : false;
            } 
        else $this->connected=false;
        if ($this->connected); echo "Sucessfull WS connection to $this->host:$this->port\n\n";
        return $this->connected;  
    }
    
    function lg_handshake()
    {
        if (!$this->connected) $this->connect();
        if ($this->connected)
        {
            $handshake =    '{"type":"register","id":"register_0","payload":{"forcePairing":false,"pairingType":"PROMPT","client-key":"HANDSHAKEKEYGOESHERE","manifest":{"manifestVersion":1,"appVersion":"1.1","signed":{"created":"20140509","appId":"com.lge.test","vendorId":"com.lge","localizedAppNames":{"":"LG Remote App","ko-KR":"리모컨 앱","zxx-XX":"ЛГ R�мot� AПП"},"localizedVendorNames":{"":"LG Electronics"},"permissions":["TEST_SECURE","CONTROL_INPUT_TEXT","CONTROL_MOUSE_AND_KEYBOARD","READ_INSTALLED_APPS","READ_LGE_SDX","READ_NOTIFICATIONS","SEARCH","WRITE_SETTINGS","WRITE_NOTIFICATION_ALERT","CONTROL_POWER","READ_CURRENT_CHANNEL","READ_RUNNING_APPS","READ_UPDATE_INFO","UPDATE_FROM_REMOTE_APP","READ_LGE_TV_INPUT_EVENTS","READ_TV_CURRENT_TIME"],"serial":"2f930e2d2cfe083771f68e4fe7bb07"},"permissions":["LAUNCH","LAUNCH_WEBAPP","APP_TO_APP","CLOSE","TEST_OPEN","TEST_PROTECTED","CONTROL_AUDIO","CONTROL_DISPLAY","CONTROL_INPUT_JOYSTICK","CONTROL_INPUT_MEDIA_RECORDING","CONTROL_INPUT_MEDIA_PLAYBACK","CONTROL_INPUT_TV","CONTROL_POWER","READ_APP_STATUS","READ_CURRENT_CHANNEL","READ_INPUT_DEVICE_LIST","READ_NETWORK_STATE","READ_RUNNING_APPS","READ_TV_CHANNEL_LIST","WRITE_NOTIFICATION_TOAST","READ_POWER_STATE","READ_COUNTRY_INFO"],"signatures":[{"signatureVersion":1,"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="}]}}}';
            if (isset($this->lg_key)) 
            $handshake = str_replace('HANDSHAKEKEYGOESHERE',$this->lg_key,$handshake);
            else  $handshake =    '{"type":"register","id":"register_0","payload":{"forcePairing":false,"pairingType":"PROMPT","manifest":{"manifestVersion":1,"appVersion":"1.1","signed":{"created":"20140509","appId":"com.lge.test","vendorId":"com.lge","localizedAppNames":{"":"LG Remote App","ko-KR":"리모컨 앱","zxx-XX":"ЛГ R�мot� AПП"},"localizedVendorNames":{"":"LG Electronics"},"permissions":["TEST_SECURE","CONTROL_INPUT_TEXT","CONTROL_MOUSE_AND_KEYBOARD","READ_INSTALLED_APPS","READ_LGE_SDX","READ_NOTIFICATIONS","SEARCH","WRITE_SETTINGS","WRITE_NOTIFICATION_ALERT","CONTROL_POWER","READ_CURRENT_CHANNEL","READ_RUNNING_APPS","READ_UPDATE_INFO","UPDATE_FROM_REMOTE_APP","READ_LGE_TV_INPUT_EVENTS","READ_TV_CURRENT_TIME"],"serial":"2f930e2d2cfe083771f68e4fe7bb07"},"permissions":["LAUNCH","LAUNCH_WEBAPP","APP_TO_APP","CLOSE","TEST_OPEN","TEST_PROTECTED","CONTROL_AUDIO","CONTROL_DISPLAY","CONTROL_INPUT_JOYSTICK","CONTROL_INPUT_MEDIA_RECORDING","CONTROL_INPUT_MEDIA_PLAYBACK","CONTROL_INPUT_TV","CONTROL_POWER","READ_APP_STATUS","READ_CURRENT_CHANNEL","READ_INPUT_DEVICE_LIST","READ_NETWORK_STATE","READ_RUNNING_APPS","READ_TV_CHANNEL_LIST","WRITE_NOTIFICATION_TOAST","READ_POWER_STATE","READ_COUNTRY_INFO"],"signatures":[{"signatureVersion":1,"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="}]}}}';
            echo "Sending LG handshake\n$handshake\n";
            $response = $this->send(hybi10Encode($handshake));
            if ($response)
            {
                echo "\nLG Handshake Response\n".json_string($response)."\n";
                $result = json_array($response);
                if ($result && array_key_exists('id',$result) &&  $result['id']=='result_0' && array_key_exists('client-key',$result['payload']))
                {
                    if ($this->lg_key == $result['payload']['client-key']);
                    echo "LG Client-Key successfully approved\n"; 
                } 
                else if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && array_key_exists('pairingType',$result['payload']) && array_key_exists('returnValue',$result['payload']))
                {
                    if ($result['payload']['pairingType'] == "PROMPT" && $result['payload']['returnValue'] == "true") 
                    {
                        $starttime = microtime(1);
                        $lg_key_received = false;
                        $error_received = false;
                        do
                        {
                            $response = @fread($this->sock, 8192);
                            $result = json_array($response);
                            if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && is_array($result['payload']) && array_key_exists('client-key',$result['payload']))
                            {
                                $lg_key_received = true;
                                $this->lg_key = $result['payload']['client-key'];
                                echo "LG Client-Key successfully received: $this->lg_key\n"; 
                            } 
                            else if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && array_key_exists('error',$result))
                            {
                                $error_received = true;
                                echo "ERROR: ".$result['error']."\n";
                            }
                            usleep(200000);
                            $time = microtime(1);
                        } 
                        while ($time-$starttime<60 && !$lg_key_received && !$error_received);
                    }
                }
            } 
            else echo "ERROR during LG handshake:\n";
        } 
        else return FALSE; 
    }

    function disconnect()
    { 
        $this->connected=false;
        @fclose($this->sock);
        echo "Connection closed to $this->host\n";
    }

    function send($msg)
    {
        @fwrite($this->sock, $msg);
        usleep(250000);
        $response = @fread($this->sock, 8192);
        return $response;
    }
    
	function send_command($cmd)
	{
		if (!$this->connected) $this->connect();
		if ($this->connected)
		{
			echo "Sending command      : $cmd\n";
			$response = $this->send(hybi10Encode($cmd));
			if ($response)
				echo "Command response     : ".json_string($response)."\n";
			else 
				echo "Error sending command: $cmd\n";
			return $response;			
		} 
	}
   //Ab hier können Funktionen hinzugefügt werden

    function turnOff() //Einschalten geht nur über WOL!
    {
        $command = '{"id":"turnOff","type":"request","uri":"ssap://system/turnOff"}';
        $this->send_command($command);
    }

    function volumeUp()
    {
        $command = '{"id":"volumeUp","type":"request","uri":"ssap://audio/volumeUp"}';
        $this->send_command($command);
    }

    function volumeDown()
    {
        $command = '{"id":"volumeDown","type":"request","uri":"ssap://audio/volumeDown"}';
        $this->send_command($command);
    }

    function message($msg) 
    { 
        $command = '{"id":"message","type":"request","uri":"ssap://system.notifications/createToast","payload":{"message":"'.$msg.'"}}'; 
        $this->send_command($command); 
    }

    function set_volume($vol)
    {
        //$command = '{"id":"setVolume","type":"request","uri":"ssap://audio/setVolume","payload":{"volume":'.$vol.'"}}';
        $command = "{\"id\":\"set_volume\",\"type\":\"request\",\"uri\":\"ssap://audio/setVolume\",\"payload\":{\"volume\":$vol}}";
        $this->send_command($command); 
    }
}    
        
function hybi10Encode($payload, $type = 'text', $masked = true) {
        $frameHead = array();
        $frame = '';
        $payloadLength = strlen($payload);

        switch ($type) {
            case 'text':
                $frameHead[0] = 129;
                break;

            case 'close':
                $frameHead[0] = 136;
                break;

            case 'ping':
                $frameHead[0] = 137;
                break;

            case 'pong':
                $frameHead[0] = 138;
                break;
        }

        if ($payloadLength > 65535)
        {
            $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
            $frameHead[1] = ($masked === true) ? 255 : 127;
            for ($i = 0; $i < 8; $i++) 
            {
                $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
            }
            if ($frameHead[2] > 127) 
            {
                $this->close(1004);
                return false;
            }
        } 
        elseif ($payloadLength > 125) 
        {
            $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
            $frameHead[1] = ($masked === true) ? 254 : 126;
            $frameHead[2] = bindec($payloadLengthBin[0]);
            $frameHead[3] = bindec($payloadLengthBin[1]);
        } 
        else    
        {
            $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
        }
        foreach (array_keys($frameHead) as $i) 
        {
            $frameHead[$i] = chr($frameHead[$i]);
        }
        if ($masked === true) 
        {
            $mask = array();
            for ($i = 0; $i < 4; $i++)
            {
                $mask[$i] = chr(rand(0, 255));
            }
            $frameHead = array_merge($frameHead, $mask);
        }
        $frame = implode('', $frameHead);
        for ($i = 0; $i < $payloadLength; $i++) 
        {
            $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
        }
        return $frame;
    }

    function generateRandomString($length = 10, $addSpaces = true, $addNumbers = true)
    {  
        $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"§$%&/()=[]{}';
        $useChars = array();
        for($i = 0; $i < $length; $i++)
        {
            $useChars[] = $characters[mt_rand(0, strlen($characters)-1)];
        }
        if($addSpaces === true)
        {
            array_push($useChars, ' ', ' ', ' ', ' ', ' ', ' ');
        }
        if($addNumbers === true)
        {
            array_push($useChars, rand(0,9), rand(0,9), rand(0,9));
        }
        shuffle($useChars);
        $randomString = trim(implode('', $useChars));
        $randomString = substr($randomString, 0, $length);
        return $randomString;
    }

    function json_array($str)
    {
        $result = json_decode(json_string($str),true);
        return $result;
    }
    
    function json_string($str)
    {
        $from = strpos($str,"{");
        $to = strripos($str,"}");
        $len = $to-$from+1;
        $result = substr($str,$from,$len);
        return $result;
    }

?> 

Danach ein weiteres:

<?php

//1. TV Einschalten und Einstellungen im TV für Steuerung via App usw. prüfen ob aktiviert

include_once '12345.ips.php';                    //2. Skript ID des "webos.inc.php" Skript eintragen

$tv = new webOSTV("192.168.x.x",3000,"");    //3. IP des TV eintragen
$tv->connect();
$tv->lg_handshake();
$tv->disconnect();  

//4. Skript ausführen
//5. Meldung am TV beachten und akzeptieren (kurzes Zeitfenster)
//6. Response abwarten und LG Client-Key notieren. "LG Client-Key successfully received: 0afd4c4xxxxxxxxxx..."
//7. Mit einem neuen Skript befehle testen


?> 

Im zweiten Skript wird unter Punkt 2 die ID des ersten Skript’s eingetragen und unter Punkt 3 die IP des LG. Dieses Skript wird nur einmal ausgeführt und erzeugt den Client-Key, welcher für die Befehls-Skripte benötigt wird.
Ein solches Skript z.B. für die Lautstärke sieht dann so aus:

<?php

include_once '17551.ips.php'; 

$vol = "25"; 
$tv = new webOSTV("192.168.x.x",3000,"abcd08fc19e14abcdb1234b3db67ca99");    // Change to the IP of your LG device                       //  
$tv->lg_handshake(); 
$tv->set_volume($vol); 

?>

Oder hier für einen Meldetext:

<?php

include_once '17551.ips.php'; 

$msg = GetValueString(56560); // ID der Meldetextvariable       //
$tv = new webOSTV("192.168.x.x",3000,"abcd08fc19e14abcdb1234b3db67ca99");    // Change to the IP of your LG device                       //  
$tv->lg_handshake(); 
$tv->message($msg); 

?>

Hier gab es auch noch mehrere andere Möglichkeiten, ansonsten suche ich die noch raus.

Das alles ist aber nicht auf meinen Mist gewachsen, das habe ich mir halt durch mehrere Recherchen herausgesucht und mit PHP kenne ich mich kaum aus.

Noch wichtig. Man kann den LG auch einschalten. Das hängt aber davon ab, ob der schon im Tiefschlaf ist oder sich noch anpingen lässt. Antwortet er nicht auf einen Ping, dann muss er mit WOL aufgeweckt werden. Da gibt’s auch etwas zu. Lässt er sich noch anpingen, geht das wiederum mit einem Skript.

Weiterhin sollte man nach einem WOL Start mindestens 30 Sekunden warten, bevor man ihn via Skript anspricht. Manchmal führt er dann zwar die Befehle aus, erzeugt aber mangels Response Fehlermeldungen im PHP-Skript.

Ich hoffe ich konnte dir als Laie etwas helfen. Sonst einfach fragen.

Gruß
Marc

@froema 1000 Dank für deine Mühe. Ich werde das heute mal mit meinen LG testen und berichten ob es läuft. Eventuell könnte man irgendwo hier im Thema mal die kompatiblen Geräte oder getesteten Modelle auflisten?!

Gruß,
Peter

Erst mal danke an alle.
Ich habe es mit dem Skript von froema probiert. Hat jedoch bei meinem OLED65CX9LA nicht funktioniert: Error during WS handshake
In einem anderen Forum fand ich einen Hinweis, das bei neueren Softwareversionen nur noch eine SSL Verbindungen über Port 3001 möglich ist.

Ich habe das Skript dann angepasst (Zeile 26 bis 37) und die Parameter bei allen anderen LG-Skripten mit ssl:// ergänzt und auf Port 3001 geändert:

$tv = new webOSTV(„ssl://192.168.0.209“,3001,…)

Mit diesen Änderungen hat es dann funktioniert.

geändertes Skript:

<?php


class webOSTV
{
    private $host, $port, $ws_key, $path, $lg_key, $sock, $connected=false, $handshaked=false;

    function __construct($host, $port=3001, $lgKey="NOKEY", $path="/")
    {
        $this->host = $host;
        $this->port = $port;
        $this->lg_key = $lgKey;
        $this->path = $path;
        $this->ws_key = $key = base64_encode(generateRandomString(16, false, true));
        if ($this->lg_key=="NOKEY") unset($this->lg_key);    
    }
        
    function connect()
    {
        $ws_handshake_cmd = "GET " . $this->path . " HTTP/1.1\r\n";
        $ws_handshake_cmd.= "Upgrade: websocket\r\n";
        $ws_handshake_cmd.= "Connection: Upgrade\r\n";
        $ws_handshake_cmd.= "Sec-WebSocket-Version: 13\r\n";            
        $ws_handshake_cmd.= "Sec-WebSocket-Key: " . $this->ws_key. "\r\n";
        $ws_handshake_cmd.= "Host: ".$this->host.":".$this->port."\r\n\r\n";
       // $this->sock = fsockopen($this->host, $this->port, $errno, $errstr, 2);

Code:
//PHP 5.6 & 7.0 Only Configuration
$context = stream_context_create(['ssl' => [
  //'ciphers' => 'RC4-MD5',
  'verify_host' => FALSE,
  'verify_peer_name' => FALSE,
  'verify_peer' => FALSE
]]);

$this->sock = stream_socket_client($this->host.':'.$this->port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
//END OF PHP 5.6 & 7.0 Only Configuration

        socket_set_timeout($this->sock, 0, 10000);
        echo     "Sending WS handshake\n$ws_handshake_cmd\n";
        $response = $this->send($ws_handshake_cmd);
        if ($response)
        {
            echo "WS Handshake Response:\n$response\n";
        } 
        else 
        echo "ERROR during WS handshake!\n";
        preg_match('#Sec-WebSocket-Accept:\s(.*)$#mU', $response, $matches);
        if ($matches) 
            {
            $keyAccept = trim($matches[1]);
            $expectedResonse = base64_encode(pack('H*', sha1($this->ws_key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
            $this->connected = ($keyAccept === $expectedResonse) ? true : false;
            } 
        else $this->connected=false;
        if ($this->connected); echo "Sucessfull WS connection to $this->host:$this->port\n\n";
        return $this->connected;  
    }
    
    function lg_handshake()
    {
        if (!$this->connected) $this->connect();
        if ($this->connected)
        {
            $handshake =    '{"type":"register","id":"register_0","payload":{"forcePairing":false,"pairingType":"PROMPT","client-key":"HANDSHAKEKEYGOESHERE","manifest":{"manifestVersion":1,"appVersion":"1.1","signed":{"created":"20140509","appId":"com.lge.test","vendorId":"com.lge","localizedAppNames":{"":"LG Remote App","ko-KR":"리모컨 앱","zxx-XX":"ЛГ R�мot� AПП"},"localizedVendorNames":{"":"LG Electronics"},"permissions":["TEST_SECURE","CONTROL_INPUT_TEXT","CONTROL_MOUSE_AND_KEYBOARD","READ_INSTALLED_APPS","READ_LGE_SDX","READ_NOTIFICATIONS","SEARCH","WRITE_SETTINGS","WRITE_NOTIFICATION_ALERT","CONTROL_POWER","READ_CURRENT_CHANNEL","READ_RUNNING_APPS","READ_UPDATE_INFO","UPDATE_FROM_REMOTE_APP","READ_LGE_TV_INPUT_EVENTS","READ_TV_CURRENT_TIME"],"serial":"2f930e2d2cfe083771f68e4fe7bb07"},"permissions":["LAUNCH","LAUNCH_WEBAPP","APP_TO_APP","CLOSE","TEST_OPEN","TEST_PROTECTED","CONTROL_AUDIO","CONTROL_DISPLAY","CONTROL_INPUT_JOYSTICK","CONTROL_INPUT_MEDIA_RECORDING","CONTROL_INPUT_MEDIA_PLAYBACK","CONTROL_INPUT_TV","CONTROL_POWER","READ_APP_STATUS","READ_CURRENT_CHANNEL","READ_INPUT_DEVICE_LIST","READ_NETWORK_STATE","READ_RUNNING_APPS","READ_TV_CHANNEL_LIST","WRITE_NOTIFICATION_TOAST","READ_POWER_STATE","READ_COUNTRY_INFO"],"signatures":[{"signatureVersion":1,"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="}]}}}';
            if (isset($this->lg_key)) 
            $handshake = str_replace('HANDSHAKEKEYGOESHERE',$this->lg_key,$handshake);
            else  $handshake =    '{"type":"register","id":"register_0","payload":{"forcePairing":false,"pairingType":"PROMPT","manifest":{"manifestVersion":1,"appVersion":"1.1","signed":{"created":"20140509","appId":"com.lge.test","vendorId":"com.lge","localizedAppNames":{"":"LG Remote App","ko-KR":"리모컨 앱","zxx-XX":"ЛГ R�мot� AПП"},"localizedVendorNames":{"":"LG Electronics"},"permissions":["TEST_SECURE","CONTROL_INPUT_TEXT","CONTROL_MOUSE_AND_KEYBOARD","READ_INSTALLED_APPS","READ_LGE_SDX","READ_NOTIFICATIONS","SEARCH","WRITE_SETTINGS","WRITE_NOTIFICATION_ALERT","CONTROL_POWER","READ_CURRENT_CHANNEL","READ_RUNNING_APPS","READ_UPDATE_INFO","UPDATE_FROM_REMOTE_APP","READ_LGE_TV_INPUT_EVENTS","READ_TV_CURRENT_TIME"],"serial":"2f930e2d2cfe083771f68e4fe7bb07"},"permissions":["LAUNCH","LAUNCH_WEBAPP","APP_TO_APP","CLOSE","TEST_OPEN","TEST_PROTECTED","CONTROL_AUDIO","CONTROL_DISPLAY","CONTROL_INPUT_JOYSTICK","CONTROL_INPUT_MEDIA_RECORDING","CONTROL_INPUT_MEDIA_PLAYBACK","CONTROL_INPUT_TV","CONTROL_POWER","READ_APP_STATUS","READ_CURRENT_CHANNEL","READ_INPUT_DEVICE_LIST","READ_NETWORK_STATE","READ_RUNNING_APPS","READ_TV_CHANNEL_LIST","WRITE_NOTIFICATION_TOAST","READ_POWER_STATE","READ_COUNTRY_INFO"],"signatures":[{"signatureVersion":1,"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="}]}}}';
            echo "Sending LG handshake\n$handshake\n";
            $response = $this->send(hybi10Encode($handshake));
            if ($response)
            {
                echo "\nLG Handshake Response\n".json_string($response)."\n";
                $result = json_array($response);
                if ($result && array_key_exists('id',$result) &&  $result['id']=='result_0' && array_key_exists('client-key',$result['payload']))
                {
                    if ($this->lg_key == $result['payload']['client-key']);
                    echo "LG Client-Key successfully approved\n"; 
                } 
                else if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && array_key_exists('pairingType',$result['payload']) && array_key_exists('returnValue',$result['payload']))
                {
                    if ($result['payload']['pairingType'] == "PROMPT" && $result['payload']['returnValue'] == "true") 
                    {
                        $starttime = microtime(1);
                        $lg_key_received = false;
                        $error_received = false;
                        do
                        {
                            $response = @fread($this->sock, 8192);
                            $result = json_array($response);
                            if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && is_array($result['payload']) && array_key_exists('client-key',$result['payload']))
                            {
                                $lg_key_received = true;
                                $this->lg_key = $result['payload']['client-key'];
                                echo "LG Client-Key successfully received: $this->lg_key\n"; 
                            } 
                            else if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && array_key_exists('error',$result))
                            {
                                $error_received = true;
                                echo "ERROR: ".$result['error']."\n";
                            }
                            usleep(200000);
                            $time = microtime(1);
                        } 
                        while ($time-$starttime<60 && !$lg_key_received && !$error_received);
                    }
                }
            } 
            else echo "ERROR during LG handshake:\n";
        } 
        else return FALSE; 
    }

    function disconnect()
    { 
        $this->connected=false;
        @fclose($this->sock);
        echo "Connection closed to $this->host\n";
    }

    function send($msg)
    {
        @fwrite($this->sock, $msg);
        usleep(250000);
        $response = @fread($this->sock, 8192);
        return $response;
    }
    
	function send_command($cmd)
	{
		if (!$this->connected) $this->connect();
		if ($this->connected)
		{
			echo "Sending command      : $cmd\n";
			$response = $this->send(hybi10Encode($cmd));
			if ($response)
				echo "Command response     : ".json_string($response)."\n";
			else 
				echo "Error sending command: $cmd\n";
			return $response;			
		} 
	}
   //Ab hier können Funktionen hinzugefügt werden

    function turnOff() //Einschalten geht nur über WOL!
    {
        $command = '{"id":"turnOff","type":"request","uri":"ssap://system/turnOff"}';
        $this->send_command($command);
    }

    function volumeUp()
    {
        $command = '{"id":"volumeUp","type":"request","uri":"ssap://audio/volumeUp"}';
        $this->send_command($command);
    }

    function volumeDown()
    {
        $command = '{"id":"volumeDown","type":"request","uri":"ssap://audio/volumeDown"}';
        $this->send_command($command);
    }

    function message($msg) 
    { 
        $command = '{"id":"message","type":"request","uri":"ssap://system.notifications/createToast","payload":{"message":"'.$msg.'"}}'; 
        $this->send_command($command); 
    }

    function set_volume($vol)
    {
        //$command = '{"id":"setVolume","type":"request","uri":"ssap://audio/setVolume","payload":{"volume":'.$vol.'"}}';
        $command = "{\"id\":\"set_volume\",\"type\":\"request\",\"uri\":\"ssap://audio/setVolume\",\"payload\":{\"volume\":$vol}}";
        $this->send_command($command); 
    }
}    
        
function hybi10Encode($payload, $type = 'text', $masked = true) {
        $frameHead = array();
        $frame = '';
        $payloadLength = strlen($payload);

        switch ($type) {
            case 'text':
                $frameHead[0] = 129;
                break;

            case 'close':
                $frameHead[0] = 136;
                break;

            case 'ping':
                $frameHead[0] = 137;
                break;

            case 'pong':
                $frameHead[0] = 138;
                break;
        }

        if ($payloadLength > 65535)
        {
            $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
            $frameHead[1] = ($masked === true) ? 255 : 127;
            for ($i = 0; $i < 8; $i++) 
            {
                $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
            }
            if ($frameHead[2] > 127) 
            {
                $this->close(1004);
                return false;
            }
        } 
        elseif ($payloadLength > 125) 
        {
            $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
            $frameHead[1] = ($masked === true) ? 254 : 126;
            $frameHead[2] = bindec($payloadLengthBin[0]);
            $frameHead[3] = bindec($payloadLengthBin[1]);
        } 
        else    
        {
            $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
        }
        foreach (array_keys($frameHead) as $i) 
        {
            $frameHead[$i] = chr($frameHead[$i]);
        }
        if ($masked === true) 
        {
            $mask = array();
            for ($i = 0; $i < 4; $i++)
            {
                $mask[$i] = chr(rand(0, 255));
            }
            $frameHead = array_merge($frameHead, $mask);
        }
        $frame = implode('', $frameHead);
        for ($i = 0; $i < $payloadLength; $i++) 
        {
            $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
        }
        return $frame;
    }

    function generateRandomString($length = 10, $addSpaces = true, $addNumbers = true)
    {  
        $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"§$%&/()=[]{}';
        $useChars = array();
        for($i = 0; $i < $length; $i++)
        {
            $useChars[] = $characters[mt_rand(0, strlen($characters)-1)];
        }
        if($addSpaces === true)
        {
            array_push($useChars, ' ', ' ', ' ', ' ', ' ', ' ');
        }
        if($addNumbers === true)
        {
            array_push($useChars, rand(0,9), rand(0,9), rand(0,9));
        }
        shuffle($useChars);
        $randomString = trim(implode('', $useChars));
        $randomString = substr($randomString, 0, $length);
        return $randomString;
    }

    function json_array($str)
    {
        $result = json_decode(json_string($str),true);
        return $result;
    }
    
    function json_string($str)
    {
        $from = strpos($str,"{");
        $to = strripos($str,"}");
        $len = $to-$from+1;
        $result = substr($str,$from,$len);
        return $result;
    }

?>

Moin,

leider auch das gleiche bei mir.
Ein Schritt an sich weiter, bei den anderen Scripten im Netz habe ich nicht mal eine Verbindung bekommen.

Sending WS handshake
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: JiIibjZ5VUoxYSlCbW9tRA==
Host: 192.168.100.169:3001


ERROR during WS handshake!
Sucessfull WS connection to 192.168.100.169:3001

Sending WS handshake
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: JiIibjZ5VUoxYSlCbW9tRA==
Host: 192.168.100.169:3001


ERROR during WS handshake!
Sucessfull WS connection to 192.168.100.169:3001

Sending WS handshake
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: JiIibjZ5VUoxYSlCbW9tRA==
Host: 192.168.100.169:3001


ERROR during WS handshake!
Sucessfull WS connection to 192.168.100.169:3001

Sending WS handshake
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: JiIibjZ5VUoxYSlCbW9tRA==
Host: 192.168.100.169:3001


ERROR during WS handshake!
Sucessfull WS connection to 192.168.100.169:3001

Connection closed to 192.168.100.169

Gruß
Thomas

In Zeile 5 steht aber noch $port=3000. Müsste der dann nicht auch auf 3001 gesetzt werden?

nur mal so ins Blaue, wie sieht es aus, wenn Du statt ssl wss schreibst,
also $tv = new webOSTV(„wss://192.168.0.209“,3001,…) ?

image

Gruß,
Loerdy

Habe meinen Beitrag noch ergänzt. Es funktioniert jedoch auch mit dem port 3000 bei mir. Offenbar wird die function bei mir nicht verwendet?
Habe es auf 3001 geändert.

Habe meinen Beitrag noch ergänzt. Es funktioniert bei mir mit ssl.

Hallo Zusammen,

bei mir hat leider keines der vorherigen Skripte funktioniert, deshalb hier meine Skripte für einen

LG 55GX9LA mit webOS 5.5.0-1103

Folgende 3 Skripte anlegen:

WebOS.inc.php

<?php


class webOSTV
{
    private $host, $port, $ws_key, $path, $lg_key, $sock, $connected=false, $handshaked=false;

    function __construct($host, $port=3001, $lgKey="NOKEY", $path="/")
    {
        $this->host = $host;
        $this->port = $port;
        $this->lg_key = $lgKey;
        $this->path = $path;
        $this->ws_key = $key = base64_encode(generateRandomString(16, false, true));
        if ($this->lg_key=="NOKEY") unset($this->lg_key);    
    }
        
    function connect()
    {
        $ws_handshake_cmd = "GET " . $this->path . " HTTP/1.1\r\n";
        $ws_handshake_cmd.= "Upgrade: websocket\r\n";
        $ws_handshake_cmd.= "Connection: Upgrade\r\n";
        $ws_handshake_cmd.= "Sec-WebSocket-Version: 13\r\n";            
        $ws_handshake_cmd.= "Sec-WebSocket-Key: " . $this->ws_key. "\r\n";
        $ws_handshake_cmd.= "Host: ".$this->host.":".$this->port."\r\n\r\n";
       // $this->sock = fsockopen($this->host, $this->port, $errno, $errstr, 2);

Code:
//PHP 5.6 & 7.0 Only Configuration
$context = stream_context_create(['ssl' => [
  //'ciphers' => 'RC4-MD5',
  'verify_host' => FALSE,
  'verify_peer_name' => FALSE,
  'verify_peer' => FALSE
]]);

$this->sock = stream_socket_client($this->host.':'.$this->port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
//END OF PHP 5.6 & 7.0 Only Configuration

        socket_set_timeout($this->sock, 0, 10000);
        echo     "Sending WS handshake\n$ws_handshake_cmd\n";
        $response = $this->send($ws_handshake_cmd);
        if ($response)
        {
            echo "WS Handshake Response:\n$response\n";
        } 
        else 
        echo "ERROR during WS handshake!\n";
        preg_match('#Sec-WebSocket-Accept:\s(.*)$#mU', $response, $matches);
        if ($matches) 
            {
            $keyAccept = trim($matches[1]);
            $expectedResonse = base64_encode(pack('H*', sha1($this->ws_key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
            $this->connected = ($keyAccept === $expectedResonse) ? true : false;
            } 
        else $this->connected=false;
        if ($this->connected); echo "Sucessfull WS connection to $this->host:$this->port\n\n";
        return $this->connected;  
    }
    
    function lg_handshake()
    {
        if (!$this->connected) $this->connect();
        if ($this->connected)
        {
            $handshake =    '{"type":"register","id":"register_0","payload":{"forcePairing":false,"pairingType":"PROMPT","client-key":"HANDSHAKEKEYGOESHERE","manifest":{"manifestVersion":1,"appVersion":"1.1","signed":{"created":"20140509","appId":"com.lge.test","vendorId":"com.lge","localizedAppNames":{"":"LG Remote App","ko-KR":"리모컨 앱","zxx-XX":"ЛГ R�мot� AПП"},"localizedVendorNames":{"":"LG Electronics"},"permissions":["TEST_SECURE","CONTROL_INPUT_TEXT","CONTROL_MOUSE_AND_KEYBOARD","READ_INSTALLED_APPS","READ_LGE_SDX","READ_NOTIFICATIONS","SEARCH","WRITE_SETTINGS","WRITE_NOTIFICATION_ALERT","CONTROL_POWER","READ_CURRENT_CHANNEL","READ_RUNNING_APPS","READ_UPDATE_INFO","UPDATE_FROM_REMOTE_APP","READ_LGE_TV_INPUT_EVENTS","READ_TV_CURRENT_TIME"],"serial":"2f930e2d2cfe083771f68e4fe7bb07"},"permissions":["LAUNCH","LAUNCH_WEBAPP","APP_TO_APP","CLOSE","TEST_OPEN","TEST_PROTECTED","CONTROL_AUDIO","CONTROL_DISPLAY","CONTROL_INPUT_JOYSTICK","CONTROL_INPUT_MEDIA_RECORDING","CONTROL_INPUT_MEDIA_PLAYBACK","CONTROL_INPUT_TV","CONTROL_POWER","READ_APP_STATUS","READ_CURRENT_CHANNEL","READ_INPUT_DEVICE_LIST","READ_NETWORK_STATE","READ_RUNNING_APPS","READ_TV_CHANNEL_LIST","WRITE_NOTIFICATION_TOAST","READ_POWER_STATE","READ_COUNTRY_INFO"],"signatures":[{"signatureVersion":1,"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="}]}}}';
            if (isset($this->lg_key)) 
            $handshake = str_replace('HANDSHAKEKEYGOESHERE',$this->lg_key,$handshake);
            else  $handshake =    '{"type":"register","id":"register_0","payload":{"forcePairing":false,"pairingType":"PROMPT","manifest":{"manifestVersion":1,"appVersion":"1.1","signed":{"created":"20140509","appId":"com.lge.test","vendorId":"com.lge","localizedAppNames":{"":"LG Remote App","ko-KR":"리모컨 앱","zxx-XX":"ЛГ R�мot� AПП"},"localizedVendorNames":{"":"LG Electronics"},"permissions":["TEST_SECURE","CONTROL_INPUT_TEXT","CONTROL_MOUSE_AND_KEYBOARD","READ_INSTALLED_APPS","READ_LGE_SDX","READ_NOTIFICATIONS","SEARCH","WRITE_SETTINGS","WRITE_NOTIFICATION_ALERT","CONTROL_POWER","READ_CURRENT_CHANNEL","READ_RUNNING_APPS","READ_UPDATE_INFO","UPDATE_FROM_REMOTE_APP","READ_LGE_TV_INPUT_EVENTS","READ_TV_CURRENT_TIME"],"serial":"2f930e2d2cfe083771f68e4fe7bb07"},"permissions":["LAUNCH","LAUNCH_WEBAPP","APP_TO_APP","CLOSE","TEST_OPEN","TEST_PROTECTED","CONTROL_AUDIO","CONTROL_DISPLAY","CONTROL_INPUT_JOYSTICK","CONTROL_INPUT_MEDIA_RECORDING","CONTROL_INPUT_MEDIA_PLAYBACK","CONTROL_INPUT_TV","CONTROL_POWER","READ_APP_STATUS","READ_CURRENT_CHANNEL","READ_INPUT_DEVICE_LIST","READ_NETWORK_STATE","READ_RUNNING_APPS","READ_TV_CHANNEL_LIST","WRITE_NOTIFICATION_TOAST","READ_POWER_STATE","READ_COUNTRY_INFO"],"signatures":[{"signatureVersion":1,"signature":"eyJhbGdvcml0aG0iOiJSU0EtU0hBMjU2Iiwia2V5SWQiOiJ0ZXN0LXNpZ25pbmctY2VydCIsInNpZ25hdHVyZVZlcnNpb24iOjF9.hrVRgjCwXVvE2OOSpDZ58hR+59aFNwYDyjQgKk3auukd7pcegmE2CzPCa0bJ0ZsRAcKkCTJrWo5iDzNhMBWRyaMOv5zWSrthlf7G128qvIlpMT0YNY+n/FaOHE73uLrS/g7swl3/qH/BGFG2Hu4RlL48eb3lLKqTt2xKHdCs6Cd4RMfJPYnzgvI4BNrFUKsjkcu+WD4OO2A27Pq1n50cMchmcaXadJhGrOqH5YmHdOCj5NSHzJYrsW0HPlpuAx/ECMeIZYDh6RMqaFM2DXzdKX9NmmyqzJ3o/0lkk/N97gfVRLW5hA29yeAwaCViZNCP8iC9aO0q9fQojoa7NQnAtw=="}]}}}';
            echo "Sending LG handshake\n$handshake\n";
            $response = $this->send(hybi10Encode($handshake));
            if ($response)
            {
                echo "\nLG Handshake Response\n".json_string($response)."\n";
                $result = json_array($response);
                if ($result && array_key_exists('id',$result) &&  $result['id']=='result_0' && array_key_exists('client-key',$result['payload']))
                {
                    if ($this->lg_key == $result['payload']['client-key']);
                    echo "LG Client-Key successfully approved\n"; 
                } 
                else if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && array_key_exists('pairingType',$result['payload']) && array_key_exists('returnValue',$result['payload']))
                {
                    if ($result['payload']['pairingType'] == "PROMPT" && $result['payload']['returnValue'] == "true") 
                    {
                        $starttime = microtime(1);
                        $lg_key_received = false;
                        $error_received = false;
                        do
                        {
                            $response = @fread($this->sock, 8192);
                            $result = json_array($response);
                            if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && is_array($result['payload']) && array_key_exists('client-key',$result['payload']))
                            {
                                $lg_key_received = true;
                                $this->lg_key = $result['payload']['client-key'];
                                echo "LG Client-Key successfully received: $this->lg_key\n"; 
                            } 
                            else if ($result && array_key_exists('id',$result) &&  $result['id']=='register_0' && array_key_exists('error',$result))
                            {
                                $error_received = true;
                                echo "ERROR: ".$result['error']."\n";
                            }
                            usleep(200000);
                            $time = microtime(1);
                        } 
                        while ($time-$starttime<60 && !$lg_key_received && !$error_received);
                    }
                }
            } 
            else echo "ERROR during LG handshake:\n";
        } 
        else return FALSE; 
    }

    function disconnect()
    { 
        $this->connected=false;
        @fclose($this->sock);
        echo "Connection closed to $this->host\n";
    }

    function send($msg)
    {
        @fwrite($this->sock, $msg);
        usleep(250000);
        $response = @fread($this->sock, 8192);
        return $response;
    }
    
	function send_command($cmd)
	{
		if (!$this->connected) $this->connect();
		if ($this->connected)
		{
			echo "Sending command      : $cmd\n";
			$response = $this->send(hybi10Encode($cmd));
			if ($response)
				echo "Command response     : ".json_string($response)."\n";
			else 
				echo "Error sending command: $cmd\n";
			return $response;			
		} 
	}
   //Ab hier können Funktionen hinzugefügt werden

    function turnOff() //Einschalten geht nur über WOL!
    {
        $command = '{"id":"turnOff","type":"request","uri":"ssap://system/turnOff"}';
        $this->send_command($command);
    }

    function volumeUp()
    {
        $command = '{"id":"volumeUp","type":"request","uri":"ssap://audio/volumeUp"}';
        $this->send_command($command);
    }

    function volumeDown()
    {
        $command = '{"id":"volumeDown","type":"request","uri":"ssap://audio/volumeDown"}';
        $this->send_command($command);
    }

    function message($msg) 
    { 
        $command = '{"id":"message","type":"request","uri":"ssap://system.notifications/createToast","payload":{"message":"'.$msg.'"}}'; 
        $this->send_command($command); 
    }

    function set_volume($vol)
    {
        //$command = '{"id":"setVolume","type":"request","uri":"ssap://audio/setVolume","payload":{"volume":'.$vol.'"}}';
        $command = "{\"id\":\"set_volume\",\"type\":\"request\",\"uri\":\"ssap://audio/setVolume\",\"payload\":{\"volume\":$vol}}";
        $this->send_command($command); 
    }
}    
        
function hybi10Encode($payload, $type = 'text', $masked = true) {
        $frameHead = array();
        $frame = '';
        $payloadLength = strlen($payload);

        switch ($type) {
            case 'text':
                $frameHead[0] = 129;
                break;

            case 'close':
                $frameHead[0] = 136;
                break;

            case 'ping':
                $frameHead[0] = 137;
                break;

            case 'pong':
                $frameHead[0] = 138;
                break;
        }

        if ($payloadLength > 65535)
        {
            $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
            $frameHead[1] = ($masked === true) ? 255 : 127;
            for ($i = 0; $i < 8; $i++) 
            {
                $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
            }
            if ($frameHead[2] > 127) 
            {
                $this->close(1004);
                return false;
            }
        } 
        elseif ($payloadLength > 125) 
        {
            $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
            $frameHead[1] = ($masked === true) ? 254 : 126;
            $frameHead[2] = bindec($payloadLengthBin[0]);
            $frameHead[3] = bindec($payloadLengthBin[1]);
        } 
        else    
        {
            $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
        }
        foreach (array_keys($frameHead) as $i) 
        {
            $frameHead[$i] = chr($frameHead[$i]);
        }
        if ($masked === true) 
        {
            $mask = array();
            for ($i = 0; $i < 4; $i++)
            {
                $mask[$i] = chr(rand(0, 255));
            }
            $frameHead = array_merge($frameHead, $mask);
        }
        $frame = implode('', $frameHead);
        for ($i = 0; $i < $payloadLength; $i++) 
        {
            $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
        }
        return $frame;
    }

    function generateRandomString($length = 10, $addSpaces = true, $addNumbers = true)
    {  
        $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"§$%&/()=[]{}';
        $useChars = array();
        for($i = 0; $i < $length; $i++)
        {
            $useChars[] = $characters[mt_rand(0, strlen($characters)-1)];
        }
        if($addSpaces === true)
        {
            array_push($useChars, ' ', ' ', ' ', ' ', ' ', ' ');
        }
        if($addNumbers === true)
        {
            array_push($useChars, rand(0,9), rand(0,9), rand(0,9));
        }
        shuffle($useChars);
        $randomString = trim(implode('', $useChars));
        $randomString = substr($randomString, 0, $length);
        return $randomString;
    }

    function json_array($str)
    {
        $result = json_decode(json_string($str),true);
        return $result;
    }
    
    function json_string($str)
    {
        $from = strpos($str,"{");
        $to = strripos($str,"}");
        $len = $to-$from+1;
        $result = substr($str,$from,$len);
        return $result;
    }

?>

WebOS.handshake

→ Zeile 5+7 mit euren Daten anpassen und den Anweisungen im Skript folgen

<?php

//1. TV Einschalten und Einstellungen im TV für Steuerung via App usw. prüfen ob aktiviert

include_once 'xxxxx.ips.php';                    //2. Skript ID des "webos.inc.php" Skript eintragen

$tv = new webOSTV("ssl://192.168.xxx.xxx",3001,"");    //3. IP des TV eintragen

$tv->connect();
$tv->lg_handshake();
$tv->disconnect();  

//4. Skript ausführen
//5. Meldung am TV beachten und akzeptieren (kurzes Zeitfenster)
//6. Response abwarten und LG Client-Key notieren. "LG Client-Key successfully received: 0afd4c4xxxxxxxxxx..."
//7. Mit einem neuen Skript befehle testen


?>


WebOS.mitteilung.Hallo Welt

→ Zeile 3+6 mit euren Daten anpassen

<?php

include_once 'XXXXX.ips.php'; //ID des Skript WebOS.inc.php

$msg = "Hallo Welt";
$tv = new webOSTV("ssl://192.168.xxx.xxx",3001,"xxxxxxxxxxxxxxxxxxxxxxxxxxxx");    // Change to the IP of your LG device  an the Key 
$tv->lg_handshake();
$tv->message($msg);