将Php转换为Python,base64编码

时间:2016-06-14 14:07:17

标签: php python sockets base64 smart-tv

我是一名Python初学者,并将PHP脚本转换为python。它将我的LG SmartTV连接到我的Raspi,但连接功能存在问题

原始php代码

       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']))
                {
                    // LG client-key received: COMPARE!!!
                    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']))
                {    // LG TV is prompting for access rights
                    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;            
        } 
    }

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

    function power_off()
    {
        $command = "{"id":"power_off","type":"request","uri":"ssap://system/turnOff"}";
        $this->send_command($command);
    }

    function set_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':
                // first byte indicates FIN, Text-Frame (10000001):
                $frameHead[0] = 129;
                break;

            case 'close':
                // first byte indicates FIN, Close Frame(10001000):
                $frameHead[0] = 136;
                break;

            case 'ping':
                // first byte indicates FIN, Ping frame (10001001):
                $frameHead[0] = 137;
                break;

            case 'pong':
                // first byte indicates FIN, Pong frame (10001010):
                $frameHead[0] = 138;
                break;
        }

        // set mask and payload length (using 1, 3 or 9 bytes)
        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]);
            }

            // most significant bit MUST be 0 (close connection if frame too big)
            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;
        }

        // convert frame-head to string:
        foreach (array_keys($frameHead) as $i) {
            $frameHead[$i] = chr($frameHead[$i]);
        }

        if ($masked === true) {
            // generate a random mask:
            $mask = array();
            for ($i = 0; $i < 4; $i++) {
                $mask[$i] = chr(rand(0, 255));
            }

            $frameHead = array_merge($frameHead, $mask);
        }
        $frame = implode('', $frameHead);
        // append payload to frame:
        for ($i = 0; $i < $payloadLength; $i++) {
            $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
        }

        return $frame;
    }

我的python代码

 def connect(self):
    ws_handshake_cmd = "GET "+str(self._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: "+ str(self._wskey) + "\r\n"
    ws_handshake_cmd += "Host: "+ str(self._host)+":"+str(self._port)+"\r\n\r\n"

    try:
        self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self._sock.connect((self._host, self._port))
        #self._sock.settimeout(20)
    except:
        print("Verbindung zu ", str(self._host), "nicht möglich!")

    print("Sending WS handshake", ws_handshake_cmd)

    response = self.send(ws_handshake_cmd.encode('utf-8'))
    if response == '':
        print("ERROR during WS handshake!")
    else:
        print("WS Handshake Response:", response)
        matches = re.search('Sec-WebSocket-Accept:\s*(.*=)', response)
        returnkey = matches.group().strip()
        #print("Match in response ",keyAccept)

    tvkey = '' # von TV 28 stellen
    wskey = str(self._wskey).encode('utf8') #zu TV 26 stellen
    key = str('258EAFA5-E914-47DA-95CA-C5AB0DC85B11').encode('utf8')
    keys = str("%s%s" % (wskey , key)).encode('utf8')
    hash = hashlib.sha1(keys).hexdigest()
    print(hash)
    asci = bytes(hash.encode('utf-8'))
    print(asci)
    print(base64.standard_b64encode(asci))
    expectedResonse = base64.b64encode(asci)
    print("gerechneter wert",expectedResonse)

    if returnkey == expectedResonse:
        self._connected = True
        print("Key Akzeptiert")
    else:
        self._connected = False
        print("Key nicht Akzeptiert")

    if self._connected:
        print( "Sucessfull WS connection to", self._host, ": ", self._port)
    return self._connected

def lg_handshake(self):
    if self._connected == False:
        self.connect()
    if self._connected:
        handshake ='{"type":"register","id":"register_0","payload":{"forcePairing":False,"pairingType":"PROMPT","client-key":"'+str(self._wskey)+'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 self._tvkey != '':
            handshake = str.replace(self._handshakecode,self._tvkey)
        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=="}]}}}'
            print("Sending LG handshake",handshake)
        response = self.send(self.hybi10Encode(handshake))
        if response == True:
            print("LG Handshake Response",self.json_string(response))
            result = self.json_array(response)
            if result and ('id' in result) and  result['id']=='result_0' and ('client-key' in result['payload']):

                #// LG client-key received: COMPARE!!!
                if self._lg_key == result['payload']['client-key']:
                    print("LG Client-Key successfully approved")
                else:
                    if result and ('id'in result) and  result['id']=='register_0' and ('pairingType' in result['payload']) and ('returnValue' in result['payload']):
                        #// LG TV is prompting for access rights
                        if (result['payload']['pairingType'] == 'PROMPT') and (result['payload']['returnValue'] == 'True'):
                            starttime = time.time()
                            lg_key_received = False
                            error_received = False
                            while (time-starttime<60 and not lg_key_received and not error_received):
                                response = self._sock.read(8192)
                                result = self.json_array(response)
                                if result == True and ('id' in result) and  result['id']=='register_0' and is_array(result['payload']) and ('client-key' in result['payload']):
                                    lg_key_received = True
                                    self._lg_key = result['payload']['client-key']
                                    print("LG Client-Key successfully received:",self._lg_key)
                                elif result and ('id' in result) and  result['id']=='register_0' and ('error' in result):
                                    error_received = True
                                    print("ERROR: ",result['error'])
                                time.sleep(200000 / 1000000.0)#usleep(200000)
                                time = time.time()
        else:
            print("ERROR during LG handshake:")
    else:
        return False

现在的问题是,tvkey与wskey + key不同,但我认为它不对。

连接电视tvkey =键?!

1 个答案:

答案 0 :(得分:0)

指定问题,我认为它只是与行 $ expectedResonse = base64_encode(pack('H *',sha1($ this-&gt; ws_key。'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); 我在python中不知道这个......