Skip to content
This repository has been archived by the owner on Jul 10, 2024. It is now read-only.

QSeries #114

Open
Cmac2016 opened this issue May 29, 2019 · 61 comments
Open

QSeries #114

Cmac2016 opened this issue May 29, 2019 · 61 comments

Comments

@Cmac2016
Copy link

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.

@cyclops1982
Copy link

Show what you have tried and which errors you get!

@jbro
Copy link

jbro commented Aug 27, 2019

I've just tried the using samsungctl on a Q series:

If I do:

curl http://192.168.0.10:8001/api/v2

Then the TV pops up with a "Give smart device access prompt", if how ever I run samsungctl as below, no popup shows.

$ samsungctl --host 192.168.0.10 --method websocket KEY_MENU

Returns

Traceback (most recent call last):
File "/home/jumbotron/.local/bin/samsungctl", line 11, in
sys.exit(main())
File "/home/jumbotron/.local/lib/python3.6/site-packages/samsungctl/main.py", line 110, in main
with Remote(config) as remote:
File "/home/jumbotron/.local/lib/python3.6/site-packages/samsungctl/remote.py", line 11, in init
self.remote = RemoteWebsocket(config)
File "/home/jumbotron/.local/lib/python3.6/site-packages/samsungctl/remote_websocket.py", line 30, in init
self._read_response()
File "/home/jumbotron/.local/lib/python3.6/site-packages/samsungctl/remote_websocket.py", line 72, in _read_response
raise exceptions.UnhandledResponse(response)
samsungctl.exceptions.UnhandledResponse: {'event': 'ms.channel.unauthorized'}

@Cmac2016
Copy link
Author

This is basically the same things I have tried except I used Chrome web socket tool to send the commands. Get the same result however. It allows me to authorize but then all commands return:
'event': 'ms.channel.unauthorized

@jbro
Copy link

jbro commented Aug 29, 2019

So I actually got something working, but without using samsungctl.

First off the remote control endpoint is only availiable on using secure websocket.

Secondly it needs ?token=<8 didgit number> added to the URL, where the eight digit number is returned after the device is allowed access using dialog the pop up on the tv.

@Cmac2016
Copy link
Author

using ws client I get an initial response of:

06:48:15 -> (json)

{
"data": {
"clients": [
{
"attributes": {
"name": null
},
"connectTime": 1567075825828,
"deviceName": "Smart Device",
"id": "1194e510-7e44-48f2-a15a-6c35d992d125",
"isHost": false
}
],
"id": "1194e510-7e44-48f2-a15a-6c35d992d125"
},
"event": "ms.channel.connect"
}

but no commands i send after this seem to work. always get unauthorized.

@cyclops1982
Copy link

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

@jbro
Copy link

jbro commented Aug 29, 2019

If you connect to the remote control endpoint on secure websocket like:

$ wscat -n --connect wss://192.168.0.10:8002/api/v2/channels/samsung.remote.control

Then a little dialog pops up on the tv, that asks you if you want to allow the device, after pressing allow some json like below is returned containing the token:

> connected (press CTRL+C to quit)
< {"data":{"clients":[{"attributes":{"name":null},"connectTime":1567087962961,"deviceName":"Smart Device","id":"c8f69ec8-8379-4a29-8c80-43446c0a2c7","isHost":false}],"id":"c8f69ec8-8379-4a29-8c80-43446c0a2c7","token":"16131682"},"event":"ms.channel.connect"}

@Cmac2016
Copy link
Author

Cmac2016 commented Aug 29, 2019 via email

@jbro
Copy link

jbro commented Aug 29, 2019

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"}}"')

@Cmac2016
Copy link
Author

Cmac2016 commented Aug 29, 2019 via email

@jbro
Copy link

jbro commented Aug 29, 2019

Sounds very reasonable, maybe you should use the name when getting the token, I don't know if it is a pair.

@Cmac2016
Copy link
Author

Cmac2016 commented Aug 29, 2019 via email

@jbro
Copy link

jbro commented Aug 29, 2019

No problem, let me know when you have it in master, then I'll test it out :)

@Cmac2016
Copy link
Author

any time I try wss// it will not connect.
I have to use ws// on port 8001

here are my results....sadly still no success

21:41:12 Connecting to "ws://10.0.0.244:8001/api/v2/channels/ms.remote.control?name="ChrisRemote""

21:41:12 Successfull connected to "ws://10.0.0.244:8001/api/v2/channels/ms.remote.control?name="ChrisRemote""

21:41:12 -> (json)

{
"data": {
"clients": [
{
"attributes": {
"name": ""ChrisRemote""
},
"connectTime": 1567129408905,
"deviceName": ""ChrisRemote"",
"id": "c2273afe-ce5f-426-a39-bfaee018976a",
"isHost": false
}
],
"id": "c2273afe-ce5f-426-a39-bfaee018976a"
},
"event": "ms.channel.connect"
}
21:41:18 <- (json)

{
"method": "ms.remote.control",
"params": {
"Cmd": "Click",
"DataOfCmd": "KEY_POWER",
"Option": false,
"TypeOfRemote": "SendRemoteKey"
}
}
21:41:18 -> (json)

{
"data": {
"message": "unrecognized method value : ms.remote.control"
},
"event": "ms.error"
}

if I format the request using samsung.remote.control:

21:46:41 Connecting to "ws://10.0.0.244:8001/api/v2/channels/samsung.remote.control"

21:46:41 Successfull connected to "ws://10.0.0.244:8001/api/v2/channels/samsung.remote.control"

21:46:41 -> (json)

{
"event": "ms.channel.unauthorized"
}
21:46:41 Connection to "ws://10.0.0.244:8001/api/v2/channels/samsung.remote.control" closed

21:46:41 Error: (1006)

@jbro
Copy link

jbro commented Aug 30, 2019

Oh yeah forgot to mention wss runs on port 8002, see my code above.

@Cmac2016
Copy link
Author

I tried wss on port 8002.

Result:

06:15:09 Connecting to "wss://10.0.0.244:8002/api/v2/channels/samsung.remote.control"

06:15:09 Connection to "wss://10.0.0.244:8002/api/v2/channels/samsung.remote.control" closed

06:15:09 Error: (1006)

Seems my display actively refuses a connection on that port.
Only port that does anything is 8001

@jbro
Copy link

jbro commented Aug 30, 2019

I don't know if this is after a certain version of either the TV or firmware. My TV is a Q7 I think running the newest firmware as of last week.

@Cmac2016
Copy link
Author

Cmac2016 commented Sep 1, 2019 via email

@gbrissey
Copy link

gbrissey commented Sep 6, 2019

I have a Q8, and would like get this working on mine.
Be happy to try it out on my Q8.
I'm a bit confuse as to which branch and
which repo I should actually pull from. (i.e. which is the latest)

There is the
yours samsungctl ,
and one by Kdschlossar (which I believe a fork of yours)

I've been trying this on my linux machine to get it to work,
but in the end I would like to get this working on my HASSIO based Home Assistant.
planning to use the AppDaemon add-on so I can use python to call this package

I'm currently using your master branch.
I'll try the wscat or ws I see if I can get the token.

Any other suggestion let me know.
Thanks

@cyclops1982
Copy link

cyclops1982 commented Sep 8, 2019

HI,

So, i have a UE43RU7400UXXU. Which is officially a series 7 TV. My API version is 2.0.25.
I've all other code that i've seen online not to work, as i never got a token.

Now, the below code seems to work.

To get a token:

const WebSocket = require('ws');

function base64Encode(aStr) {
    return Buffer.from(aStr).toString('base64');
};


var appname = base64Encode("SamsungTvRemote2");
var baseURL = "wss://192.168.1.22:8002/api/v2/channels/samsung.remote.control?name=" + appname


function getToken() {
    var uri = baseURL;
    console.log('URL: ' + uri)
    let ws = new WebSocket(uri, {
        rejectUnauthorized: false
    });

    ws.on('message', (response) => {
        console.log("SOCKET 1 RECEIVED: " + response);

        var data = JSON.parse(response);

        if (data.event === "ms.channel.connect") {
            console.log("YOUR TOKEN IS:" + data.data.token);
        }
    })
}

`
When you run this, the TV will ask you for 'permission' for the app. The name will be the same as above "SamsungTvRemote2". After you approve that (click Allow), then you'll get the token from the K2. It can also time-out at this point, so don't be slow as a snail :)

After that, the following code will work to do 'volume down'
const WebSocket = require('ws');

function base64Encode(aStr) {
    return Buffer.from(aStr).toString('base64');
};


var appname = base64Encode("SamsungTvRemote2");
var baseURL = "wss://192.168.1.22:8002/api/v2/channels/samsung.remote.control?name=" + appname
var token = 22936467; # REPLACE WITH YOUR TOKEN


function doStuff() {

    uri = baseURL+"&token="+token;
    console.log('URL: ' + uri)
    ws = new WebSocket(uri, {
        rejectUnauthorized: false
    });


    ws.on('message', (response) => {
        console.log("SOCKET 2 RECEIVED:" + response);

        var data = JSON.parse(response);


        var cmd = {
            method: 'ms.remote.control',
            params: {
                Cmd: 'Click',
                DataOfCmd: 'KEY_VOLDOWN',
                Option: 'false',
                TypeOfRemote: 'SendRemoteKey'
            }
        }
        var str = JSON.stringify(cmd);
        console.log('SOCKET 2 SEND:' + str);
        ws.send(str);

    });


}


doStuff();

For me, this works. I'm not sure how long this token lasts. I tend to power down the TV every night, not sure if it forgets the code. THe token i got last week didn't work.

@gbrissey
Copy link

gbrissey commented Sep 8, 2019

cyclops1982,

I was all excited to try this out, until I realized this wasn't python. Darn.
What language is this? Go?

I'll see if I can convert it to python and get it to work.

@Cmac2016
Copy link
Author

Cmac2016 commented Sep 9, 2019 via email

@Cmac2016
Copy link
Author

Cmac2016 commented Sep 9, 2019 via email

@gbrissey
Copy link

gbrissey commented Sep 9, 2019

Cyclops1982, et.al.,

Based on your code I cobbled together a python 3.X web-client to see if I could get a token back from my Samsung Q8FN

I can now get my TV to display the pop-up to give permission for my device to be connected.
And when I do I do get a token back!!! (got to be fast on that remote button press to allow)

response:
{"data":{"clients":[{"attributes":{"name":"SamsungTvRemote2"},"connectTime":1568005339390,"deviceName":"SamsungTvRemote2","id":"81177dfe-2c84-4ec9-a614-7f2a4a81fad","isHost":false}],"id":"81177dfe-2c84-4ec9-a614-7f2a4a81fad","token":"14517545"},"event":"ms.channel.connect"}

I still have a few issues, when I go to the external device list (on the TV) for devices that have been allowed to connect. The entry which should have the name of the device shows [Invalid UTF-8]
So I either forgot some option or the encoding is not quite right.
The code is just gets the the token

I also noticed, in my case at least, the TV must be TV source (i.e. not in app like YouTube or Netflix for the pop-up to occur. I also had my AVR off as well (may not be necessary)

If you run this code more than once be sure to delete the device from the Samsung's TV External Device List! Otherwise you'll probably get some sort of connection refused error.

here is the python code:

import base64
import sys
import re
try:
import thread
except ImportError:
import _thread as thread
import time
import websocket
import ssl

appname = 'SamsungTvRemote2'
baseURL = "wss://192.168.1.23:8002/api/v2/channels/samsung.remote.control?name=" + appname

def on_message(ws, message):
print('on_message')
print(message)

def on_error(ws, error):
print('on_error')
print(error)

def on_close(ws):
print('on_close')
print("### closed ###")

def on_open(ws):
def run(*args):
for i in range(3):
time.sleep(1)
ws.send("Hello %d" % i)
time.sleep(2)
ws.close()
print("thread terminating...")
thread.start_new_thread(run, ())

if name == "main":
websocket.enableTrace(True)
uri = baseURL;
print('URL: ' + uri)
print("")
ws = websocket.WebSocketApp(uri,
on_message = on_message,
on_error = on_error,
on_close = on_close)

ws.on_open = on_open
# disable of the SSL Cert requirement
ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) 

Hope this help others, and maybe someone can tell me why I get Invalid UTF-8 for a device in the TV external device list

@gbrissey
Copy link

gbrissey commented Sep 9, 2019

For some reason all the indenting for the python got removed in the post.
Sorry about that.

@Cmac2016
Copy link
Author

Cmac2016 commented Sep 9, 2019 via email

@gbrissey
Copy link

gbrissey commented Sep 10, 2019

I'm not exactly sure except when I tried connected to 8002 it always refused connection until I specified the websocket not use use SSL Certificate. e.g. sslopt={"cert_reqs": ssl.CERT_NONE}.
You don't have that port blocked by your router (not that it should).
As I mentioned before my TV had to be in a specific configuration to observe the pop-up.....
Also on occasion I need to power off and power on the TV before I get the prompt
TV is a QN65Q8FNB
My software version displayed is: T-KTM2AKUC-1270.6, BT-S
if that is any help.....

@gbrissey
Copy link

Here's a example python that sends the KEY_MENU to the TV

I know, the indentation are all gone. Somebody tell how to get them to stay.
Looks fine before I submit.

python 3.X code

``# -- coding: utf-8 --
import sys
import re
try:
import thread
except ImportError:
import _thread as thread
import time
import websocket
import ssl
import json

def sendCmd(ws,keycmd):
'''
json cmd format
cmd = {
'method' : 'ms.remote.control',
'params': {
'Cmd': 'Click',
'DataOfCmd': 'KEY_MENU',
'Option': 'false',
'TypeOfRemote': 'SendRemoteKey'
}
}
'''
cmddict = { 'method' : 'ms.remote.control' }
paramdict = { 'Cmd': 'Click', 'DataOfCmd': 'Bogus_KEY', 'Option': 'false','TypeOfRemote': 'SendRemoteKey'}
paramdict['DataOfCmd'] = keycmd
cmddict['params'] = paramdict;
json_str = json.dumps(cmddict)
print(json_str)
ws.send(json_str);

if name == "main":
websocket.enableTrace(True)
appname = "SamsungTvRemote2"
base_url = "wss://192.168.1.23:8002/api/v2/channels/samsung.remote.control?name={}&token={}"
token = "57216234"
url = base_url.format(appname,token) # e.g. name=SamsungTvRemote2&token=47216513
print(url)
ws = websocket.create_connection(url, sslopt={"cert_reqs": ssl.CERT_NONE})
#ws = None
# bring up menu
sendCmd(ws,'KEY_MENU')
time.sleep(5)
# close the menu
sendCmd(ws,'KEY_MENU')
ws.close()

@cyclops1982
Copy link

@gbrissey The appname that you use, needs to be a base64 encoded string. That's why it's complaining about the UTF-8 issue.
The javascript has a little base64encode method and that's waht's being used.

Once you have the token, does it stay the same? I've noticed that i can send a few commands but then it just responds with No Authorization. I've also noticed that turning off the TV and then ON again seems to 'forget' the previous code. Ideally - i'd like to just get one code once.

I wonder if it has to do with the fact that we use a websocket and/or not close it properly, or something like that?

About the code formatting: https://help.github.com/en/articles/creating-and-highlighting-code-blocks

@gbrissey
Copy link

@cyclops1982 strange you ask about a POST/GET interface
There is one.
once you TV is on try this: POST this http://192.168.1.23:8080/ws/app/Netflix
this should start up Netflix on the TV
I was using Postman to POST or GET from the TV.
This might be easier t use if it weren't for having to figure out all the commands yourself.

@gbrissey
Copy link

@cyclops1982
I'm now seeing the behavior you are reporting. Each command to the TV generates a pop-up to allow.
Very odd indeed. Very inconsistent behavior. Not sure what's going on here.
And if I convert my UTF-8 string to base64 the websocket throws an error

@Cmac2016
Copy link
Author

Cmac2016 commented Sep 11, 2019 via email

@raydog153
Copy link

There was a ton of work on fork of this repo that addressed the websocket logic you guys are working thru. I think you should try out the develop branch here https://github.com/kdschlosser/samsungctl/tree/develop

@gbrissey
Copy link

@raydog153 I've tried this repo and both the develop and master branch.
The development gave me python errors and the master hung without appearing to do anything.
i didn't see any responses to posted issues, so I wasn't sure if this was still an active project.

Have you been successful with this samsungvtl ?

@raydog153
Copy link

Sad to say I have one of those 2014 TVs that are next to impossible to get working if firmware was updated. I do not have port 8001/8002 enabled at all, only very few ports open. I do have port 8080 so some of the UPNP stuff I can get to work, change volume, WOL. My model number is UN40H5203.

I was helping to debug it for a while, then life happened and I gave up for the moment. Need to be careful depending on which python version you run. The repo owner was quite active, put a ton of work into it, and would be the best starting point. Could also look at the closed/open issues for help in understanding the logic too...

@Cmac2016
Copy link
Author

Cmac2016 commented Sep 12, 2019 via email

@gbrissey
Copy link

@raydog153
I've been trying to get Kdschosser repo samsungctl to work, got his development branch to run, but it seems to heavly rely on UPNP to discover the TV even when given the ip of the TV. However UPNP relies (someone correct me if I'm wrong) on UDP port 1900 which is not open on my TV, I'm guessing Samsung decided this was a security issue and closed this port. Thus the samsungctl will never find the TV. It's too bad all that work is now blocked. Not sure I can unravel the UPNP from te rest.

My biggest issue is is obtaining a token that will last between sessions (power down then up of the TV) I can get a token but it only lasts the one session.
Can anybody help us.

@gbrissey
Copy link

@Cmac2016
Can you share your C# code, and have you been able to get a token that last even after turning the TV on/off/on?

@gbrissey
Copy link

I've solved the token not lasting between power cycles of the TV.
On My Q8FN it's merely a setting on the TV, that a bit embarrassing.
TV settings and find "external devices manager", "devices connection manager" or similar.
There should be option for "confirmation message". Choose "first time only" or "never".

@xchwarze
Copy link

@gbrissey
Copy link

@xchwarze Hey thanks for posting back to me. I definitely will check out your api and component

@jametron
Copy link

jametron commented Nov 14, 2019

Thanks @gbrissey, @Cmac2016 and @jbro for the discussion! I used bits of your code above with the token and ssl setting to get it to work on my NU7120 using port 8002. Oddly enough I never get pop-ups on the TV screen or any changes to the list of external devices.

I'm a little bit disappointed that this WebSocket only enables you to emulate the buttons that already exist on the IR remote (and the SmartThings app) - what I really want is to have a QWERTY keyboard to speed up searching for programmes in Netflix etc. Can anybody point me in the direction of a repo that does that?

Lastly, a noob question: why are a lot of people hiding the TV's IP address in their posts? Is it really a security risk stating it explicitly?

Thanks!

@ooii
Copy link

ooii commented Nov 18, 2019

Lastly, a noob question: why are a lot of people hiding the TV's IP address in their posts? Is it really a security risk stating it explicitly?

I'm not a security expert but I don't think publishing the internal IP addresses is a security risk. I'd say that if someone enters your network, discovering the IP addresses will be easy. However, when I send logs, I edit/hide my IP addresses :) Probably to do like all the people or not to show how am I configuring my network. That statement does not change what I said before but just reveals how stupid I am.

@Galicarnax
Copy link

Galicarnax commented Jan 27, 2021

I tried to control Samsung The Frame 75'' QLED 4K with samsungctl, without success. I then tried to track down the problem connecting directly via websocket:

wscat -c "ws://192.168.0.140:8001"

I had authorized my Linux desktop before that, so I recieved the answer:

Connected (press CTRL+C to quit)
< {"data":{"clients":[{"attributes":{"name":null},"connectTime":1611729559806,"deviceName":"Smart Device","id":"72507a17-aa93-4440-bb76-aa36467585a","isHost":false}],"id":"72507a17-aa93-4440-bb76-aa36467585a"},"event":"ms.channel.connect"}

However, when I try to send control commands, I get the response unrecognized method value:

> {"method":"ms.remote.control","params":{"Cmd":"Click","DataOfCmd":"KEY_POWER","Option":false,"TypeOfRemote":"SendRemoteKey"}}"
< {"data":{"message":"unrecognized method value : ms.remote.control"},"event":"ms.error"}

After googling, I found another possible method to send (ms.channel.emit), and tried it:

> {"method":"ms.channel.emit","params":{"event": "ed.installedApp.get", "to":"host"}}

The TV doesn't send any response to this (and nothing happens on the TV), but apprantly it knows the method ms.channel.emit.

So my problem seems to be not authorization, but new method names. I failed to find them in Samsung API docs. Is it possible to ask the TV to list all avaialble methods?

@Galicarnax
Copy link

Galicarnax commented Jan 29, 2021

Ok, got it working, following jbro's comments (using manual secure websocket connection, not via samsungctl)

@AleksandarDev
Copy link

AleksandarDev commented Feb 16, 2021

@Galicarnax I got response from TV (QE65Q70RATXXH) for {"method":"ms.channel.emit","params":{"event": "ed.installedApp.get", "to":"host"}} . Here's the sample response:

{
  "data": {
    "data": [
      {
        "appId": "111299001912",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/111299001912/250x250.png",
        "is_lock": 0,
        "name": "YouTube"
      },
      {
        "appId": "org.tizen.browser",
        "app_type": 4,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/webbrowser/250x250.png",
        "is_lock": 0,
        "name": "Internet"
      },
      {
        "appId": "11101200001",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/11101200001/250x250.png",
        "is_lock": 0,
        "name": "Netflix"
      },
      {
        "appId": "3201710015016",
        "app_type": 1,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/3201710015016/250x250.png",
        "is_lock": 0,
        "name": "SmartThings"
      },
      {
        "appId": "3201511006428",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/3201511006428/250x250.png",
        "is_lock": 0,
        "name": "Rakuten TV"
      },
      {
        "appId": "3201512006785",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/3201512006785/250x250.png",
        "is_lock": 0,
        "name": "Prime Video"
      },
      {
        "appId": "121299000101",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/121299000101/250x250.png",
        "is_lock": 0,
        "name": "TuneIn"
      },
      {
        "appId": "3201803015852",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/3201803015852/250x250.png",
        "is_lock": 0,
        "name": "Flying Fish 2"
      },
      {
        "appId": "org.tizen.example.STVOpenTKApp1",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/org.tizen.example.STVOpenTKApp1/250x250.png",
        "is_lock": 0,
        "name": "STVOpenTKApp1"
      },
      {
        "appId": "3201710015037",
        "app_type": 1,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/3201710015037/250x250.png",
        "is_lock": 0,
        "name": "Gallery"
      },
      {
        "appId": "20192100002",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/20192100002/250x250.png",
        "is_lock": 0,
        "name": "e-Manual"
      },
      {
        "appId": "3201601007250",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/3201601007250/250x250.png",
        "is_lock": 0,
        "name": "Google Play Movies"
      },
      {
        "appId": "3201909019271",
        "app_type": 2,
        "icon": "/opt/share/webappservice/apps_icon/FirstScreen/3201909019271/250x250.png",
        "is_lock": 0,
        "name": "PrivacyChoices"
      }
    ]
  },
  "event": "ed.installedApp.get",
  "from": "host"
}

STVOpenTKApp1 is my custom app.

@Galicarnax
Copy link

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.

@AleksandarDev
Copy link

AleksandarDev commented Feb 16, 2021

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
Copy link

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
Copy link

AleksandarDev commented Feb 17, 2021

@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
Copy link

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
Copy link

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
Copy link

m439 commented Aug 3, 2021

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
Copy link

xchwarze commented Aug 3, 2021

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
Copy link

mStirner commented Oct 8, 2022

@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
Copy link

mStirner commented Oct 9, 2022

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
Copy link

Silverviql commented Oct 24, 2022

@AleksandarDev

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

@hunghuytra28081
Copy link

hunghuytra28081 commented Nov 28, 2022

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!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests