Posts: 8
Threads: 2
Joined: Jan 2020
Reputation:
2
17.02.2020, 09:58
(This post was last modified: 17.02.2020, 10:00 by arnocl .)
Is there anybody who got the IP Control function of the more recent Sony Bravia TV working? I'm able to post a HTTP request trough my phone, only after pairing the device with the TV first with the default sony app. On my PC this is a little more complicated, but after following
this guide (post Jul 08, 2015) this seems to work correctly. The PC appears on my TV in the list of trusted devices, along with my phone. The POST request requires to input a pincode visualized on the screen after starting the request.
Quote: 1. Install Google Chrome
2. Install Simple Rest Client (https://chrome.google.com/webstore/detail/simple-rest-client/fhjcajmcbmldlhcimfajhfbgofnpcjmb )
3. Once Simple Rest Client is installed you should see a blue globe looking icon to the right of the URL field in Chrome. Click on that icon.
4. In the URL field of the REST Client, type in http://192.168.168.198/sony/accessControl
where you replace 192.168.168.198 with IP address of your TV.
5. Click on POST.
6. In the DATA field paste:
{"id" :13,"method" :"actRegister" ,"version" :"1.0" ,"params" :[{"clientid" :"iRule:1" ,"nickname" :"iRule" },[{"clientid" :"iRule:1" ,"value" :"yes" ,"nickname" :"iRule" ,"function" :"WOL" }]]}
7. Hit SEND. You should see a message on TV pop-up with PIN code and a Username and Password message pop-up in the Browser.
Leave Username blank and in password field put in the PIN code that is displayed on TV.
It seems the TV needs to trust the device sending requests. Is there a way to enable this with the logicmachine? Previous threads don't seem to work in my case (
Sony Bravia script and
Sony Simple IP Protocol ).
This is the code I tried to use:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
function ipControlTV (
service ,
cmd )
require (
'socket' )
ip =
"192.168.1.135"
port =
80
host =
"http://" ..
ip ..
"/sony/" ..
service
reqs =
"POST /sony/" ..
service ..
" HTTP/1.1 \r\n" ..
"HOST: " ..
ip ..
" \r\n" ..
"X-Auth-PSK: **** \r\n" ..
"Content-Type: application/json; charset=UTF-8 \r\n " ..
"\r\n" ..
cmd ..
"\r\n\r\n"
sock =
socket.tcp ()
sock :
settimeout (
3 )
res ,
err =
sock :
connect (
ip ,
port )
if res then
res ,
err =
sock :
send (
reqs )
if res then
log (
res ,
err )
else
log (
'send failed: ' ..
tostring (
err ))
end
else
log (
'connect failed: ' ..
tostring (
err ))
end
sock :
close ()
end
And to call my code (toggle of power object):
Code:
1 2 3 4 5 6 7 8 9 10
power =
event.getvalue ()
command =
""
if (
power )
then
command =
'{ \\"method\\": \\"setPowerStatus\\", \\"id\\": 55, \\"params\\": [{\\"status\\": true}], \\"version\\": \\"1.0\\" }'
else
command =
'{ \\"method\\": \\"setPowerStatus\\", \\"id\\": 55, \\"params\\": [{\\"status\\": false}], \\"version\\": \\"1.0\\" }'
end
ipControlTV (
"system" ,
command )
I keep getting the following error:
Code:
1 2 3 4
*
arg :
1
*
string :
JSON Format Error
*
arg :
2
*
number :
400
Posts: 8223
Threads: 43
Joined: Jun 2015
Reputation:
475
Just remove all \\ from command strings.
More correct approach is to encode data via JSON:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
require (
'json' )
power =
event.getvalue ()
command =
json.encode ({
method =
'setPowerStatus' ,
id =
55 ,
version =
'1.0' ,
params = {
{
status =
power }
}
})
ipControlTV (
"system" ,
command )
Posts: 139
Threads: 44
Joined: Dec 2017
Reputation:
4
17.02.2020, 19:13
(This post was last modified: 17.02.2020, 23:40 by benanderson_475 .)
Hi,
Why do you try Http post command to a tcp socket??
Try this, i have it working on Sony 2019 tv with no auth required as such (apart from the Xauth-psk as defined in the tv settings) also the protocol is well documented here
https://pro-bravia.sony.net/develop/inte...index.html
i just started learning lua so im sure there are some improvements to make to this script.
Change ip adress below to match tv and update ["X-Auth-PSK"] = "123456789", with your pre shared key from the tv
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
local http =
require (
"socket.http" )
local ltn12 =
require (
"ltn12" )
require (
'json' )
local path_system =
"http://192.168.1.21/sony/system"
local path_avContent =
'http://192.168.1.21/sony/avContent'
local payl = {
Pwr_on =
[[ {"method": "setPowerStatus","id": 55,"params": [{"status": true}],"version": "1.0"} ]] ,
Pwr_off =
[[ {"method": "setPowerStatus","id": 55,"params": [{"status": false}],"version": "1.0"} ]] ,
Pwr_req =
[[ {"method": "getPowerStatus","id": 50,"params": [],"version": "1.0"} ]] ,
Pwr_Get_system =
[[{"method": "getSystemInformation","id": 33,"params": [],"version": "1.0"}]] ,
Set_input_hdmi3 =
[[ {"method": "setPlayContent","id": 101,"params": [{"uri": "extInput:hdmi?port=3"}],"version": "1.0"} ]] ,
Set_req =
[[ {"method": "getPlayingContentInfo","id": 103,"params": [],"version": "1.0"} ]] ,
vol_set =
[[ {"method": "setAudioVolume","id": 98,"params": [{"volume": "5","ui": "on","target": "speaker"}],"version": "1.2"} ]] ,
vol_req =
[[ {"method": "getVolumeInformation", "id": 33, "params": [], "version": "1.0"} ]] ,
reboot =
[[ {"method": "requestReboot","id": 10,"params": [],"version": "1.0"} ]]
}
function sony_do_cmd (
sony_cmd )
pwr =
string.match (
sony_cmd ,
"Pwr_" )
set =
string.match (
sony_cmd ,
"Set_" )
if pwr then
path =
path_system
payload =
payl [
sony_cmd ]
end
if set then
path =
path_avContent
payload =
payl [
sony_cmd ]
end
local response_body = { }
local res ,
code ,
response_headers ,
status =
http.request
{
url =
path ,
method =
"POST" ,
headers =
{
[
"Accept" ] =
"*/*" ,
[
"Content-Type" ] =
"application/x-www-form-urlencoded" ,
[
"X-Auth-PSK" ] =
"123456789" ,
[
"Content-Length" ] =
payload :
len ()
},
source =
ltn12.source.string (
payload ),
sink =
ltn12.sink.table (
response_body )
}
log (
json.decode (
response_body ))
end
Posts: 8
Threads: 2
Joined: Jan 2020
Reputation:
2
Thanks @benanderson_475 for pointing me in the right direction! Everything is working as it should, guess I got a little mixed up. The guide is indeed self explanatory.
Posts: 8
Threads: 2
Joined: Jan 2020
Reputation:
2
22.02.2020, 09:29
(This post was last modified: 22.02.2020, 09:39 by arnocl .)
I cleaned up your code a little to be tailored more to my needs. Also included a status object checker, convenient to get a feedback of the actual settings of the TV.
Common Functions:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
function ipControlSonyTV (
service ,
command )
local http =
require (
"socket.http" )
local ltn12 =
require (
"ltn12" )
require (
"json" )
local ip =
"192.168.1.135"
local response_body = { }
local res ,
code ,
response_headers ,
status =
http.request
{
url =
"http://" ..
ip ..
"/sony/" ..
service ,
method =
"POST" ,
headers =
{
[
"HOST" ] =
ip ,
[
"Accept" ] =
"*/*" ,
[
"Content-Type" ] =
"application/x-www-form-urlencoded" ,
[
"X-Auth-PSK" ] =
"************" ,
[
"Content-Length" ] =
command :
len ()
},
source =
ltn12.source.string (
command ),
sink =
ltn12.sink.table (
response_body )
}
response =
json.decode (
response_body [
1 ])
return response [
"result" ][
1 ]
end
Resident Script (every 2 seconds or as much as needed):
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
command =
[[ {"method": "getPowerStatus","id": 50,"params": [],"version": "1.0"} ]]
powerStatus =
ipControlSonyTV (
"system" ,
command )
powerStatus =
powerStatus [
"status" ]
if (
powerStatus ==
"active" )
then
grp.checkwrite (
'5/0/2' ,
1 ,
1 )
elseif (
powerStatus ==
"standby" )
then
grp.checkwrite (
'5/0/2' ,
0 ,
1 )
end
if (
powerStatus ==
"active" )
then
command =
[[ {"method": "getVolumeInformation", "id": 33, "params": [], "version": "1.0"} ]]
volumeInfo =
ipControlSonyTV (
"audio" ,
command )
volumeStatus =
volumeInfo [
1 ][
"volume" ]
muteStatus =
volumeInfo [
1 ][
"mute" ]
grp.checkwrite (
'5/0/5' ,
volumeStatus ,
1 )
grp.checkwrite (
'5/0/7' ,
muteStatus ,
1 )
command =
[[ {"method": "getPlayingContentInfo","id": 103,"params": [],"version": "1.0"} ]]
sourceStatus =
ipControlSonyTV (
"avContent" ,
command )
sourceStatus =
sourceStatus [
"uri" ]
sourceStatus =
tonumber (
string.sub (
sourceStatus , -
1 ))
grp.checkwrite (
'5/0/9' ,
sourceStatus ,
1 )
end
Every control object has it's own event script
Power:
Code:
1 2 3 4 5 6 7 8 9
power =
event.getvalue ()
if (
power )
then
command =
[[ {"method": "setPowerStatus","id": 55,"params": [{"status": true}],"version": "1.0"} ]]
else
command =
[[ {"method": "setPowerStatus","id": 55,"params": [{"status": false}],"version": "1.0"} ]]
end
ipControlSonyTV (
"system" ,
command )
Volume Step:
Code:
1 2 3 4 5 6 7 8 9
volumeDown =
event.getvalue ()
if (
volumeDown )
then
command =
[[ {"method": "setAudioVolume","id": 98,"params": [{"volume": "-1","ui": "on","target": "speaker"}],"version": "1.2"} ]]
else
command =
[[ {"method": "setAudioVolume","id": 98,"params": [{"volume": "+1","ui": "on","target": "speaker"}],"version": "1.2"} ]]
end
ipControlSonyTV (
"audio" ,
command )
Volume:
Code:
1 2 3 4 5
volume =
event.getvalue ()
command =
[[ {"method": "setAudioVolume","id": 98,"params": [{"volume": "]] ..
volume ..
[[","ui": "on","target": "speaker"}],"version": "1.2"} ]]
ipControlSonyTV (
"audio" ,
command )
Mute:
Code:
1 2 3 4 5 6 7 8 9
mute =
event.getvalue ()
if (
mute )
then
command =
[[ {"method": "setAudioMute","id": 601,"params": [{"status": true}],"version": "1.0"} ]]
else
command =
[[ {"method": "setAudioMute","id": 601,"params": [{"status": false}],"version": "1.0"} ]]
end
ipControlSonyTV (
"audio" ,
command )
Source Select:
Code:
1 2 3 4 5 6 7 8 9 10 11
source =
event.getvalue ()
power =
grp.getvalue (
'5/0/2' )
if (
not power )
then
grp.write (
'5/0/1' ,
1 )
os.sleep (
1 )
end
command =
[[ {"method": "setPlayContent","id": 101,"params": [{"uri": "extInput:hdmi?port=]] ..
source ..
[["}],"version": "1.0"} ]]
ipControlSonyTV (
"avContent" ,
command )
Posts: 139
Threads: 44
Joined: Dec 2017
Reputation:
4
23.09.2020, 03:45
(This post was last modified: 23.09.2020, 03:46 by benanderson_475 .)
in case anyone can use it, Updated user library for sony tv ip control
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
require (
'json' )
Sony_ip =
'192.168.1.6'
X_Auth_Psk =
"XXXXXXX9"
path_system =
'/sony/system'
path_avContent =
'/sony/avContent'
path_audio =
'/sony/audio'
path_ircc =
'/sony/IRCC'
function Sony_request (
host ,
url ,
payload )
ltn12 =
require (
'ltn12' )
http =
require (
'socket.http' )
response_body = {}
res ,
err =
http.request {
url =
'http://' ..
host ..
url ,
method =
'POST' ,
headers =
{
[
"Accept" ] =
"*/*" ,
[
"Content-Type" ] =
"application/x-www-form-urlencoded" ,
[
"X-Auth-PSK" ] =
X_Auth_Psk ,
[
"Content-Length" ] =
payload :
len ()
},
source =
ltn12.source.string (
payload ),
sink =
ltn12.sink.table (
response_body )
}
if response_body then
resp =
json.encode (
response_body )
resp =
json.decode (
resp )
if resp [
2 ]
then
resp =
table.concat (
resp )
resp =
json.decode (
resp )
else
resp =
json.decode (
resp [
1 ])
end
return resp
else
return nil ,
err
end
end
function Sony_Soap_request (
host ,
url ,
IRCC )
local body ,
http ,
ltn12 ,
sink ,
res ,
err
ltn12 =
require (
'ltn12' )
http =
require (
'socket.http' )
body =
[[<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:X_SendIRCC xmlns:u="urn:schemas-sony-com:service:IRCC:1">
<IRCCCode>]] ..
IRCC.. [[</IRCCCode>
</u:X_SendIRCC>
</s:Body></s:Envelope>]]
Soap_response_body = {}
res ,
err =
http.request {
url =
'http://' ..
host ..
url ,
method =
'POST' ,
headers =
{
[
"Host" ] =
host ,
[
"Connection" ] =
"keep-alive" ,
[
"Accept" ] =
"*/*" ,
[
"Content-Type" ] =
"text/xml; charset=UTF-8" ,
[
"X-Auth-PSK" ] =
X_Auth_Psk ,
[
"Content-Length" ] = #
body ,
[
"Soapaction" ] =
'"urn:schemas-sony-com:service:IRCC:1#X_SendIRCC"'
},
source =
ltn12.source.string (
body ),
sink =
ltn12.sink.table (
Soap_response_body )
}
if Soap_response_body then
return Soap_response_body
else
return nil ,
err
end
end
function encode_json_message (
method ,
id ,
params ,
version )
json_msg =
json.encode ({
method =
method ,
id =
id ,
params = {
params },
version =
version
})
return json_msg
end
function Sony_pwr (
state )
Sony_request (
Sony_ip ,
path_system ,
encode_json_message (
"setPowerStatus" ,
55 , {
status =
state },
"1.0" ))
end
function Sony_set_input_hdmi1 ()
Sony_request (
Sony_ip ,
path_avContent ,
encode_json_message (
"setPlayContent" ,
101 , {
uri =
"extInput:hdmi?port=1" },
"1.0" ))
end
function Sony_set_input_hdmi2 ()
Sony_request (
Sony_ip ,
path_avContent ,
encode_json_message (
"setPlayContent" ,
101 , {
uri =
"extInput:hdmi?port=2" },
"1.0" ))
end
function Sony_set_input_hdmi3 ()
Sony_request (
Sony_ip ,
path_avContent ,
encode_json_message (
"setPlayContent" ,
101 , {
uri =
"extInput:hdmi?port=3" },
"1.0" ))
end
function Sony_set_input_tv ()
Sony_request (
Sony_ip ,
path_avContent ,
encode_json_message (
"setPlayContent" ,
101 , {
uri =
"tv:dvbt" },
"1.0" ))
end
function Sony_set_volume (
level )
res =
Sony_request (
Sony_ip ,
path_audio ,
encode_json_message (
"setAudioVolume" ,
98 , {
volume =
level ,
ui =
"on" ,
target =
"" },
"1.2" ))
end
function Sony_set_audio_mute (
state )
Sony_request (
Sony_ip ,
path_audio ,
encode_json_message (
"setAudioMute" ,
601 , {
status =
state },
"1.0" ))
end
function Sony_get_playing_content ()
json_msg =
encode_json_message (
"getPlayingContentInfo" ,
103 , {},
"1.0" )
res =
Sony_request (
Sony_ip ,
path_avContent ,
json_msg )
if not res.error then
title =
res.result [
1 ].
title
programme =
res.result [
1 ].
programTitle
if title then
grp.write (
'1/1/1' ,
title )
end
if programme then
grp.write (
'1/1/2' ,
programme )
end
end
return title ,
programme
end
function Sony_get_power_status ()
pwr_res =
Sony_request (
Sony_ip ,
path_system ,
encode_json_message (
"getPowerStatus" ,
50 , {},
"1.0" ))
pwr_res =
pwr_res.result [
1 ].
status
return pwr_res
end
function Sony_get_volume_info ()
vol_res =
Sony_request (
Sony_ip ,
path_audio ,
encode_json_message (
"getVolumeInformation" ,
33 , {},
"1.0" ))
vol_res =
vol_res.result [
1 ][
1 ].
volume
return vol_res
end
function Sony_get_remoteController_info ()
res =
Sony_request (
Sony_ip ,
path_system ,
encode_json_message (
"getRemoteControllerInfo" ,
54 , {},
"1.0" ))
rc_codes = {}
res =
res.result [
2 ]
for i =
1 , #
res do
name =
res [
i ].
name
value =
res [
i ].
value
rc_codes [
name ] =
value
end
storage.set (
'RC_Codes' ,
rc_codes )
return rc_codes
end
function req_channel_delayed (
delay )
os.sleep (
delay )
Sony_get_playing_content ()
end
function Sony_send_key (
IRCC_name )
rc_codes =
storage.get (
'RC_Codes' )
if not rc_codes then
rc_codes =
Sony_get_remoteController_info ()
end
IRCC_key_name =
rc_codes [
IRCC_name ]
Sony_Soap_request (
Sony_ip ,
path_ircc ,
IRCC_key_name )
if IRCC_name ==
"ChannelDown" or IRCC_name ==
"ChannelUp" then
req_channel_delayed (
0.5 )
end
end
function Sony_get_content_count ()
res =
Sony_request (
Sony_ip ,
path_avContent ,
encode_json_message (
"getContentCount" ,
11 , {
source =
"tv:dvbt" },
"1.1" ))
return res.result [
1 ].
count
end
function Sony_get_content_list ()
local num =
Sony_get_content_count ()
res =
Sony_request (
Sony_ip ,
path_avContent ,
encode_json_message (
"getContentList" ,
88 , {
stIdx =
0 ,
cnt =
num ,
uri =
"tv:dvbt" },
"1.5" ))
res =
res.result [
1 ]
uri_s = {}
for i =
1 , #
res do
uri =
res [
i ].
uri
title =
res [
i ].
title
uri_s [
title ] =
uri
end
storage.set (
'Chan_uri' ,
uri_s )
return uri_s
end
function Sony_Chanell (
chan )
uri_C =
storage.get (
'Chan_uri' )
if not uri_C then
uri_C =
Sony_get_content_count ()
end
res =
Sony_request (
Sony_ip ,
path_avContent ,
encode_json_message (
"setPlayContent" ,
101 , {
uri =
uri_C [
chan ]},
"1.0" ))
req_channel_delayed (
0.2 )
return res
end