sermayoral / ha-samsungtv-encrypted

Samsung TV Encrypted Models (H & J Series) custom component for Home Assistant
Apache License 2.0
39 stars 24 forks source link

new method getSmpPorts() fails on UE40JU4600K #10

Closed RinoGaetano94 closed 4 years ago

RinoGaetano94 commented 4 years ago

Hi,

I'm tring your component with a UE40JU4600K but this method cannot find my TV's services, because it uses port 9197 for the RenderingControl and a different path (http://:9197/dmr) and port 7677 with path http://:7677/MediaTVServer2. Can you handle this configuration? Thanks

image

image

EDIT: this is a correct GetVolume request sniffed with Wireshark

POST /upnp/control/RenderingControl1 HTTP/1.1
SOAPACTION: "urn:schemas-upnp-org:service:RenderingControl:1#GetVolume"
Content-Length: 352
Content-Type: text/xml
Content-Encoding: utf-8
Host: 192.168.178.26:9197
Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

<s:Body>

<u:GetVolume xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"><InstanceID>0</InstanceID><Channel>Master</Channel></u:GetVolume>

</s:Body>

</s:Envelope>

EDIT2: Even if I manually set te services path and port, the method SendSOAP fails. The line that generate error is dataBuffer = client.recv(4096), returning timed out

pablolassalle commented 4 years ago

@sermayoral

I copied this 2.3.1 version, I have restarted home assistant after that, but log still showing the same message. I am attaching a screenshot to show the error message and the version of bs4 and lxml I have installed on my venv.

image

pablolassalle commented 4 years ago

@sermayoral I managed to solve the issue by using this solution I found googling:

sudo apt-get install libxslt1-dev libxml2 python-dev sudo pip3 install --upgrade lxml

Since I am not an expert, I am only an entusiast, I understand that by installing this packages on my raspbian (not inside my venv) solved the problem. Please correct me if I am wrong.

sermayoral commented 4 years ago

@pablolassalle its quite possible. Try it!

pablolassalle commented 4 years ago

@sermayoral Here I am again with the results of my last test:

After solved the problem of lxml library, the component V2.3 is not showing error messages, now I have debug messages, but still not possible to power off the TV, nor control the volume by using the slider. Now I have a drop down list where I can select sources, but the only source in the list is "TV", not HDMI1 nor HDMI2 (I have two devices connected to those HDMI inputs). If I select TV on that list, the TV change its sources to TV, so select source is working, the only problem is there is only one option to chose.

Here is the log: home-assistant.log

sermayoral commented 4 years ago

@pablolassalle Your TV is responding to uPNP requests. The sources connected are:

<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <u:GetSourceListResponse xmlns:u="urn:samsung.com:service:MainTVAgent2:1">
            <Result>OK</Result>
            <SourceList>
                <?xml version="1.0" encoding="UTF-8" ?>
                <SourceList>
                    <CurrentSourceType>HDMI1</CurrentSourceType>
                    <ID>13</ID>
                    <Source>
                        <SourceType>TV</SourceType>
                        <ID>0</ID>
                        <Editable>No</Editable>
                        <EditNameType/>
                        <DeviceName>NONE</DeviceName>
                        <Connected>Yes</Connected>
                        <SupportView>Yes</SupportView>
                    </Source>
                    <Source>
                        <SourceType>AV</SourceType>
                        <ID>1</ID>
                        <Editable>Yes</Editable>
                        <EditNameType>NONE</EditNameType>
                        <DeviceName/>
                        <Connected>No</Connected>
                        <SupportView>Yes</SupportView>
                    </Source>
                    <Source>
                        <SourceType>COMPONENT</SourceType>
                        <ID>7</ID>
                        <Editable>Yes</Editable>
                        <EditNameType>NONE</EditNameType>
                        <DeviceName/>
                        <Connected>No</Connected>
                        <SupportView>Yes</SupportView>
                    </Source>
                    <Source>
                        <SourceType>HDMI1</SourceType>
                        <ID>13</ID>
                        <Editable>Yes</Editable>
                        <EditNameType>NONE</EditNameType>
                        <DeviceName/>
                        <Connected>Yes</Connected>
                        <SupportView>Yes</SupportView>
                    </Source>
                    <Source>
                        <SourceType>HDMI2</SourceType>
                        <ID>14</ID>
                        <Editable>Yes</Editable>
                        <EditNameType>NONE</EditNameType>
                        <DeviceName/>
                        <Connected>Yes</Connected>
                        <SupportView>No</SupportView>
                    </Source>
                    <Source>
                        <SourceType>HDMI3/DVI</SourceType>
                        <ID>15</ID>
                        <Editable>Yes</Editable>
                        <EditNameType>NONE</EditNameType>
                        <DeviceName/>
                        <Connected>No</Connected>
                        <SupportView>No</SupportView>
                    </Source>
                </SourceList>
            </SourceList>
        </u:GetSourceListResponse>
    </s:Body>
</s:Envelope>

Is this problem remaining?

I'm seeing that SetVolume method is getting: 500 Internal Server Error (when you set volume with the slider). If you change volume manually, the correct value should appear in the slider, doesn't it? The selectsource should also work.

I need to know a thing: Can you change volume level using buttons instead of using the slider?

Well, we are going to work in the sourcelist first. Please, could you try this version attached? It fixes a bug and it has better debug logs

samsungtv_encrypted_20200417_2.zip

pablolassalle commented 4 years ago

@sermayoral this new version now shows a source list with the active connection, so I can choose from my 3 actual sources (TV, HDMI1 and HDMI2) and they work.

image

I'm seeing that SetVolume method is getting: 500 Internal Server Error (when you set volume with the slider). If you change volume manually, the correct value should appear in the slider, doesn't it? The selectsource should also work.

I need to know a thing: Can you change volume level using buttons instead of using the slider?

Changing the volume by using the slider never worked for me, using the buttons (mute, down and up) only works for a random period of time after re pairing the TV, so, when this buttons stop working I have to re pair the TV, and they stars to work again, but maybe 10hs, 24h, or any other value, this function stops working. When volume buttons works, the slider moves, showing the correct value, but I can´t control the volume with the slider. I want to clarify that sources selection is always working, no matter if the volume buttons are working or not. Power off the TV never worked for me.

This is the log. home-assistant.log

sermayoral commented 4 years ago

@sermayoral this new version now shows a source list with the active connection, so I can choose from my 3 actual sources (TV, HDMI1 and HDMI2) and they work.

@pablolassalle Great! One less thing :-)

Changing the volume by using the slider never worked for me

That happens because the SetVolume UPNP Request get a 500 Internal Server Error with this body:

<s:Body>
    <s:Fault>
        <faultcode>s:Client</faultcode>
        <faultstring>UPnPError</faultstring>
        <detail>
            <UPnPError xmlns="urn:schemas-upnp-org:control-1-0">
                <errorCode>402</errorCode>
                <errorDescription>Invalid Args</errorDescription>
            </UPnPError>
        </detail>
    </s:Fault>
</s:Body>

I don't know why your TV does this. All the other UPNP Requests work well (GetVolume, GetSourceList, GetCurrentExternalSource, ...). I will investigate to see if I find a solution...

using the buttons (mute, down and up) only works for a random period of time after re pairing the TV, so, when this buttons stop working I have to re pair the TV, and they stars to work again, but maybe 10hs, 24h, or any other value, this function stops working.

The token of your TV model expire often. This custom component cannot control that. My TV save token very good. I've only had to pair the TV once. Maybe there is some way to make the token expire later on your TV, but you will have to investigate it.

When volume buttons works, the slider moves, showing the correct value, but I can´t control the volume with the slider.

This is normal because the GetVolume UPNP request works, but the SetVolume UPNP request does not work. I suppose if your token expire (volume buttons don't work) the component doesn't show the TV status correctly (ON, OFF).

I want to clarify that sources selection is always working, no matter if the volume buttons are working or not.

UPNP functions don't depend on the encryption token. If we can correct the SetVolume UPNP request, you can also set the volume regardless of the status of the token. With a valid token, you only are be able to send encrypted commands. Mute and Volume buttons are encrypted commands, slider and sourcelist are UPNP functions.

Power off the TV never worked for me.

Poweroff button sends an encrypted command with key KEY_POWEROFF. When your TV has a valid token, all the commands are working except this. Maybe the KEY_POWEROFF command does not work for you. I found this in roberodin's component:

"Please note that some codes are different on the 2016+ TVs. For example, KEY_POWEROFF is KEY_POWER on the newer TVs."

Please, can you try sending keys to your TV with other keys to see if one of them works? All the available keys are here

pablolassalle commented 4 years ago

Thanks @sermayoral, you are right, when I send the command KEY_POWER instead of KEY_POWEROFF, the TV shutsdown, So I edited the media_player.py and changed the command and now the TV turns off with the button on the home assistant card. The problem is the token expire after a power down of the TV,so I have to repair the TV everytime I turn ON the TV, which is very annoying. Just a comment, I have an app on my cellphone called "myTifi", this app is for control samsung TV and this app is able to retain a token or whatever it uses to send encrypted command to the TV, so I think there should be any other kind of token to "remember" that does not expire, but my knowledge and skills are not enough to solve it. I hope we can help me to solve the uPNP command for volume, so at leat I will be able to control the volume when my token expires.

sermayoral commented 4 years ago

Thanks @sermayoral, you are right, when I send the command KEY_POWER instead of KEY_POWEROFF, the TV shutsdown,

@pablolassalle you can use the new v2.5 and adding the 'key_power_off' property to be able to turn off your TV. Example:

media_player:
  - platform: samsungtv_encrypted
    name: "Tele Salon"
    host: !secret ip_samsung_tv
    token: !secret token_samsung_tv
    sessionid: !secret sessionid_samsung_tv
    key_power_off: "KEY_POWER"
    port: 8080

I have an app on my cellphone called "myTifi", this app is for control samsung TV and this app is able to retain a token or whatever it uses to send encrypted command to the TV, so I think there should be any other kind of token to "remember" that does not expire, but my knowledge and skills are not enough to solve it.

I don't have enough knowledge about how Samsung works with others models. I use the encryption library that I found in PySmartCrypto. Maybe someone can help us, but I just don't have the knowledge or time to do it. Sorry.

I hope we can help me to solve the uPNP command for volume, so at leat I will be able to control the volume when my token expires.

Are you still getting the '500 Internal Server Error' when you call the SetVolume method or using the slice bar? It's very strange. The call is the same for everybody. Can I see your http://samsungtvip:9197/RenderingControl_1.xml??

pablolassalle commented 4 years ago

Hi @sermayoral, sure, this is the content of the url you asked for: https://pastebin.com/3ErKierM I have udpated the component to a version 2.5 and tested the slider again, but it is not changing the volume. This is the log.

Thanks for your time and support.

home-assistant.log

sermayoral commented 4 years ago

@pablolassalle can you try this modified version?

samsungtv_encrypted_20200501.zip

pablolassalle commented 4 years ago

@sermayoral , thanks for the quick reply. I tried this new version, but nothing happend and the 500 error is still present when I try to use the slider. This is the log.

home-assistant.log

sermayoral commented 4 years ago

And this?

samsungtv_encrypted_20200501_2.zip

The power off button works for you with this version (after 2.5 release), right?

pablolassalle commented 4 years ago

@sermayoral the power off button is working after your modification on v2.5. So one less thing. THe last two modified version you send me didn't work. The lst file is working even worst, since the slider is always going back to zero, I mean it is not showng the actual volume, which previous versions did well. This is the log of the file: samsungtv_encrypted_20200501_2.zip

home-assistant.log

sermayoral commented 4 years ago

@pablolassalle Can you use a UPNP Analizer software to see what arguments your TV needs. For Windows there is a very easy and simple software: https://www.microsoft.com/es-es/p/upnp-analyser/9nblggh69pdn?activetab=pivot:overviewtab

At the begining of this threads there are examples of @RinoGaetano94 using it. Let's see if your TV responds to SetVolume commands, and what your TV needs to work

pablolassalle commented 4 years ago

@sermayoral I could manage to control the volume of the TV using the uPNP Analyzer, no arguments change, just select the position of the slider and click on invoke and the volume on the TV is set correctly.

image

sermayoral commented 4 years ago

@pablolassalle Ok, that verify your TV accept the SetVolume method. We have to find out which SOAP request UPNP Analizer is sending to the TV.

Can you try this using some network protocol analyzer such as Wireshark?

pablolassalle commented 4 years ago

@sermayoral thanks for your help with this. This is the output I get with WireShark: image

And this is the text, I think it will be more helpful for you to analyze:

Hypertext Transfer Protocol
    POST /upnp/control/RenderingControl1 HTTP/1.1\r\n
        [Expert Info (Chat/Sequence): POST /upnp/control/RenderingControl1 HTTP/1.1\r\n]
            [POST /upnp/control/RenderingControl1 HTTP/1.1\r\n]
            [Severity level: Chat]
            [Group: Sequence]
        Request Method: POST
        Request URI: /upnp/control/RenderingControl1
        Request Version: HTTP/1.1
    SOAPACTION: "urn:schemas-upnp-org:service:RenderingControl:1#SetVolume"\r\n
    Content-Length: 384\r\n
    Content-Type: text/xml\r\n
    Content-Encoding: utf-8\r\n
    Host: 192.168.220.22:9197\r\n
    Connection: Keep-Alive\r\n
    \r\n
    [Full request URI: http://192.168.220.22:9197/upnp/control/RenderingControl1]
    [HTTP request 1/1]
    [Response in frame: 2711]
    Content-encoded entity body (utf-8): 384 bytes [Error: Decompression failed]
        Data (384 bytes)
            Data: 3c3f786d6c2076657273696f6e3d22312e302220656e636f…
            [Length: 384]

I have to mention That set volume on uPnP Analyzer didn´t work at the first try, I got 501 Error qhen I tried to set the volume, then I ran the getsourcelist command on uPnP Analyzer, and then the TV shows up a message asking for permission, I accepted that and then the set volue command started to work.

I hope this helps, if you need any other test, please let me know.

Many thanks for your time!

pablolassalle commented 4 years ago

@sermayoral I am sorry Sergio, I saw there is an error message on wireshark that it doesn´t decompress something, may be it is an error or my mistake using wireshark (this is my the first time with it). I think I managed to show the body of the commands, this is the result:

POST /upnp/control/RenderingControl1 HTTP/1.1
SOAPACTION: "urn:schemas-upnp-org:service:RenderingControl:1#SetVolume"
Content-Length: 384
Content-Type: text/xml
Content-Encoding: utf-8
Host: 192.168.220.22:9197
Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?>

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

<s:Body>

<u:SetVolume xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"><InstanceID>0</InstanceID><Channel>Master</Channel><DesiredVolume>6</DesiredVolume></u:SetVolume>

</s:Body>

</s:Envelope>

HTTP/1.1 200 OK
EXT: 
CONNECTION: close
CONTENT-TYPE: text/xml; charset="utf-8"
SERVER:UPnP/1.0, Samsung AllShare Server/1.0
DATE: Mon, 11 May 2020 15:16:09 GMT
USER-AGENT: Samsung User-Agent DLNADOC/1.50
Content-Length: 293

<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><u:SetVolumeResponse xmlns:u="urn:schemas-upnp-org:service:RenderingControl:1"></u:SetVolumeResponse></s:Body></s:Envelope>
pablolassalle commented 4 years ago

@sermayoral I think I figured out, I have changed the order of the arguments sents for "SetVolume". The component is sending the "DesiredVolume" and then "Channel", but thanks to your guide (using uPnP Analyzer and wireshark) I realized that uPnP is sending first "Channel" and then "DesiredVolume". So, I modified the line definition of the sendSOAP for SetVolume and thats it.

    def set_volume_level(self, volume):
        """Volume up the media player."""
        volset = str(round(volume * 100))

        self.SendSOAP(self._upnp_ports[0], self._upnp_paths[0], self._urns[0], 'SetVolume',
                      '<InstanceID>0</InstanceID><Channel>Master</Channel><DesiredVolume>' + volset + '</DesiredVolume>',
                      '')

I hope you can add this modification for the next version, what I do not know if any other TV model will have trouble (like me) with this change.

sermayoral commented 4 years ago

@pablolassalle great. You have done the trick!! As you can see, Samsung is a headache and it traits every TV in a different way. It's very difficult to make a component that works on every SamsungTV without suffer it.

I'm going to test this to see if it works for us too. Say you later!!

EDIT: I have tested it without any issue. Its also works in that way, so i'm going to push these changes.

Well, it seems that we have solved all your problems, except for the expiry token problem that, at the moment, I have no solution. If you agree, I'm going to close this thread because its origin has been solved and you can open another issue so that we can gradually work on the token expiration problem. Surely someone will help us soon