Ape / samsungctl

Remote control Samsung televisions via a TCP/IP connection
MIT License
716 stars 189 forks source link

QSeries #114

Open Cmac2016 opened 5 years ago

Cmac2016 commented 5 years ago

Will this code work on a 2018 Q series? I have been trying to get this code to run and cannot get thru all the errors that are happening for me.

AleksandarDev commented 3 years ago

Yes, thanks, I was misguided by TV not responding with any output (which in Linux world stands for "OK" by default :) ) The only thing I'm still struggling with is how I get current TV status, e.g., if it's powered on or off (i.e. in the Art mode). Would appreciate hints.

Sending GET http://<IP>:8001/api/v2/ will return json with device.PowerState, this can be used to determine on/off.

As for getting running app, maybe GET http://192.168.0.50:8001/ws/app/YouTube

<?xml version="1.0" encoding="UTF-8"?>
<service xmlns="urn:dial-multiscreen-org:schemas:dial" dialVer="2.1" xmlns:atom="http://www.w3.org/2005/Atom">
    <name>YouTube</name>
    <options allowStop="true"/>
    <state>running</state>
    <version>2.1.493</version>
    <link rel="run" href="run"/>
    <additionalData>
        <testYWRkaXR>REDACTED</testYWRkaXR>
        <screenId>REDACTED</screenId>
        <theme>cl</theme>
        <deviceId>REDACTED</deviceId>
        <loungeToken>REDACTED</loungeToken>
        <loungeTokenRefreshIntervalMs>1500000</loungeTokenRefreshIntervalMs>
    </additionalData>
</service>

I saw somewhere alternative way to get this data. POST request to same route will open the app.

state is what I think should indicate the app is opened or running or running in background. Didn't test this yet.

EDIT: More on activating apps:

curl -X POST http://TV_IP:8001/ws/apps/Netflix

curl -X POST http://TV_IP:8001/api/v2/applications/Netflix

https://community.smartthings.com/t/samsung-smart-tv-control-with-smartthings-webcore/166506/12

Galicarnax commented 3 years ago

device.PowerState in the json shows on for me, even if the TV is in Art mode. (For QLED 75'', when I press Power button on the remote, or send KEY_POWER via websocket API, it goes to Art mode, not powers off completely, so I need to know somehow if it is in Art mode or not, before sending KEY_POWER to it, e.g., to switch it to HDMI input).

AleksandarDev commented 3 years ago

@Galicarnax Did you try /ws/app/com.samsung.art-app or /api/v2/applications/com.samsung.art-app? Is the Art app listed in installed apps?

I see HA integration has support for Art status: https://github.com/ollo69/ha-samsungtv-smart/blob/master/custom_components/samsungtv_smart/api/samsungws.py#L524

/api/v2/channels/com.samsung.art-app

and sending status request

        msg_data = {
            "request": "get_artmode_status",
            "id": gen_uuid(),
        }
        self._ws_send(
            {
                "method": "ms.channel.emit",
                "params": {
                    "data": json.dumps(msg_data),
                    "to": "host",
                    "event": "art_app_request",
                },
            },
Galicarnax commented 3 years ago

TV doesn't reply anything to this. I do it from CLI using wscat:

> { "method": "ms.channel.emit", "params": { "data": {"request": "get_artmode_status", "id": "5a74e9dc-632d-4feb-9498-cf7664fd7a5"}, "to": "host", "event": "art_app_request" } }

No answer, no error, nothing.

omsharma123 commented 3 years ago

This is what I'm using, it's not pretty but it works:

#!/usr/bin/env python3
import websocket
import ssl
import sys
import os

tv_ip = '192.168.0.10'

if sys.argv[1] == 'on':
    if os.system("ping -c 1 " + tv_ip) is 0:
        ws = websocket.create_connection('wss://192.168.0.10:8002/api/v2/channels/samsung.remote.control?name=anVtYm90cm9u&token=12368079', sslopt={"cert_reqs": ssl.CERT_NONE})
        ws.send('{"method":"ms.remote.control","params":{"Cmd":"Click","DataOfCmd":"KEY_POWER","Option":false,"TypeOfRemote":"SendRemoteKey"}}"')
        ws.send('{"method":"ms.remote.control","params":{"Cmd":"Click","DataOfCmd":"KEY_HDMI","Option":false,"TypeOfRemote":"SendRemoteKey"}}"')
    else:
        os.system('sudo etherwake -i enp4s0 c0:48:e6:19:4e:4e')

if sys.argv[1] == 'off':
    ws = websocket.create_connection('wss://192.168.0.10:8002/api/v2/channels/samsung.remote.control?name=anVtYm90cm9u&token=12368079', sslopt={"cert_reqs": ssl.CERT_NONE})
    ws.send('{"method":"ms.remote.control","params":{"Cmd":"Click","DataOfCmd":"KEY_POWER","Option":false,"TypeOfRemote":"SendRemoteKey"}}"')

this piece of code working fine but problem is that i need to re-authenticate the tv after TV POWER OFF.why this is happen again if any solution please suggest me.

m439 commented 3 years ago

After reading through everything, I'm now able to get a token and connect with that. But when I send methods, I don't get any response back. I tried the following:

import websocket
import ssl
import sys
import os

ws = websocket.create_connection('wss://192.168.0.10:8002/api/v2/channels/samsung.remote.control?name=YXNk&token=44770026', sslopt={"cert_reqs": ssl.CERT_NONE})
ws.recv()
ws.send('{"method":"ms.channel.emit","params":{"event": "ed.installedApp.get", "to":"host"}}')
ws.recv()

The first ws.recv() gives me '{"data":{"clients":[{"attributes":{"name":"YXNk","token":"44770026"},"connectTime":1628031334532,"deviceName":"YXNk","id":"5241b691-99dd-46de-b5c2-8d4402c87f","isHost":false}],"id":"5241b691-99dd-46de-b5c2-8d4402c87f"},"event":"ms.channel.connect"}\n'

but the second one doesn't return ever. Likewise, when I try to send keys, I don't get anything back, either. Can anyone think of a problem with this?

xchwarze commented 3 years ago

HI! ed.installedApp.get dont work in all Tizen OS versions! so.... in tizen5 dont work at all this requests ed.installedApp.get The dependency that HomeAssistant now uses to communicate with the TV is the one I made. I take this opportunity and I invite you all to visit https://github.com/xchwarze/samsung-tv-ws-api

mStirner commented 1 year ago

@jbro - when exactly do you get that 8 digit number? What do you do to get that token?

I have the exact same issue with my UE60J6289. No matter what i do, i cant get a auth code/token nor the "allow device" pop message on my TV. Neither does the wss/port 8002 connection with wscat works. It just "hangs" and does nothing.


const ws = new WebSocket(`ws://192.168.2.100:8001/api/v2/channels/samsung.remote.control?name="T3BlbkhhdXM="`, {
    rejectUnauthorized: false
});

console.log("Connect to:", ws.url)

ws.on("open", () => {
    console.log("Connected to", ws.url);
});

ws.on("message", (msg) => {

    let json = JSON.parse(msg);
    console.log("message", json);

    if (json.event === "ms.channel.connect") {

        console.log("connect event received", json.data.clients);

                setTimeout(() => {

                    let obj = {
                        "method": "ms.remote.control",
                        "params": {
                            "Cmd": "Click",
                            "DataOfCmd": "KEY_MUTE",
                            "Option": "false",
                            "TypeOfRemote": "SendRemoteKey"
                        }

                    };

                    console.log("Send key", obj.params.Cmd);
                    ws.send(JSON.stringify(obj));

                }, 3000);

    }

});

The example above is very simple and straight forward. I dont know why this work with my TV in the bed room (UE43KU6079) but not with my TV (UE60J6289) in the living room

mStirner commented 1 year ago

I found out why some tvs work and some not. Its the paring dialog. When i use this tool https://github.com/McKael/samtv my UE60J6289 works.

I sniffed the smart view app traffic and was able to capture the handshake, and while researching for the crypto stuff, i found the pair.go file where the paring/handshake is done.

I hope i find in the near future time to port it to node.js and document it.

Silverviql commented 1 year ago

@AleksandarDev

Do you have the option to get a list of TV apps using the 'ed.installedApp.get' command?

hunghuytra28081 commented 1 year ago

Has anyone done it with kotlin or java? I tried to convert to kotlin but it got Error: No subjectAltNames on the certificate match Please help me!