This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Sony Bravia Authentication
#1
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:
1234567891011121314151617181920212223242526272829303132
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:
12345678910
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:
1234
* arg: 1   * string: JSON Format Error * arg: 2   * number: 400
Reply
#2
Just remove all \\ from command strings.
More correct approach is to encode data via JSON:
Code:
12345678910111213
require('json') power = event.getvalue() command = json.encode({   method = 'setPowerStatus',   id = 55,   version = '1.0',   params = {     { status = power }   } }) ipControlTV("system", command)
Reply
#3
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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
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"} ]], --/system     Pwr_off = [[ {"method": "setPowerStatus","id": 55,"params": [{"status": false}],"version": "1.0"} ]], --/system     Pwr_req = [[ {"method": "getPowerStatus","id": 50,"params": [],"version": "1.0"} ]], --/system     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"} ]], --/avContent     Set_req = [[ {"method": "getPlayingContentInfo","id": 103,"params": [],"version": "1.0"} ]],   --/avContent       vol_set = [[ {"method": "setAudioVolume","id": 98,"params": [{"volume": "5","ui": "on","target": "speaker"}],"version": "1.2"} ]], -- /audio     vol_req = [[ {"method": "getVolumeInformation", "id": 33, "params": [], "version": "1.0"} ]], -- /audio         reboot = [[ {"method": "requestReboot","id": 10,"params": [],"version": "1.0"} ]]  --/system   } --********///////////// Main Command ////////////********--  function sony_do_cmd(sony_cmd) -- 'Pwr_on' , 'Pwr_off'  for power on call function,  sony_do_cmd('Pwr_on')     -- is pwr command set url   pwr = string.match(sony_cmd, "Pwr_")   set = string.match(sony_cmd, "Set_")     if pwr then     pathpath_system     payload = payl[sony_cmd]   end     if set then     pathpath_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  
Reply
#4
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.
Reply
#5
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:
123456789101112131415161718192021222324252627
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:
123456789101112131415161718192021222324
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:
123456789
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:
123456789
volumeDown = event.getvalue()  -- down = 1 | up = 0 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:
12345
volume = event.getvalue() command = [[ {"method": "setAudioVolume","id": 98,"params": [{"volume": "]] .. volume .. [[","ui": "on","target": "speaker"}],"version": "1.2"} ]] ipControlSonyTV("audio", command)

Mute:
Code:
123456789
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:
1234567891011
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)
Reply
#6
in case anyone can use it, Updated user library for sony tv ip control

Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
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, urlpayload)     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    -- log(response_body)     resp = json.encode(response_body)      resp = json.decode(resp)    -- log(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  --************************* Command  functions **************************** 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 --************************* Request Command functions **************************** function Sony_get_playing_content()   json_msg = encode_json_message("getPlayingContentInfo", 103, {}, "1.0")   res = Sony_request(Sony_ip, path_avContent, json_msg)   --- update obj with new value     if not res.error then -- cant call this function if the display is off res.error[2] =  Display Is Turned off   titleres.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 --active|standby   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 -- returns tv volume level   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 -- log(rc_codes)   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) -- needs to send ircc with soap command... --PartnerApp11, SyncMenu, FeaturedApp, MuteOff, MuteOn, AudioMixUp Teletext, AudioOutput_TVSpeaker, partnerApp10, BS, ActionMenu, SleepTimer --CS, AudioMixDown, TvInput, PartnerApp1, Forward, Hdmi3, DigitalToggle, Hdmi2, PartnerApp6, ApplicationLauncher, Blue, Stop, TvAntennaCable, --Wide, Help, AudioOutput_AudioSystem, VolumeDown, Hdmi1, Tv, PartnerApp20, OneTouchTimeRec, Down, PartnerApp19, PopUpMenu, FeaturedAppVOD, --Component2, Video1, Audio, Media, Digital, Num11, PartnerApp13, Mode3D, AndroidMenu, *AD, Component1, CursorRight, Enter, PhotoFrame, Sleep, --PartnerApp2, Assists, ChannelUp, Right, DOT, RecorderMenu, FootballMode, Green, PartnerApp14, GooglePlay, AudioOutput_Toggle, EPG, SubTitle, --FlashMinus, Input, PartnerApp18, PartnerApp5, ClosedCaption, PartnerApp16, PAP, PartnerApp15, PartnerApp12, PartnerApp9, TenKey, WakeUp --PartnerApp7, PartnerApp17, Next, PartnerApp4, PartnerApp3, Analog, PictureMode, STBMenu, TvSatellite, Jump, BSCS, Rec, Hdmi4, Ddata, YouTube --Mute, ChannelDown, OneTouchView, Home, AnalogRgb1, PictureOff, Num2, TvAnalog, Tv_Radio, , CursorDown, Num3, Num0, WirelessSubwoofer, Video2, --Confirm, DemoMode, Left, Num1, ShopRemoteControlForcedDynamic, FlashPlus, Display, Num6, GGuide, PartnerApp8, Prev, Num7, Num4, Play, Red, --TopMenu, Num5, Analog2, DUX, Return, VolumeUp, DpadCenter, Options, Num12, PicOff, Rewind, iManual, DemoSurround, MediaAudioTrack, Up, TvPower,   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 --- log(uri_s)   storage.set('Chan_uri', uri_s)   return uri_s end function Sony_Chanell(chan) -- chan is uri name and is returned by Sony_get_content_list() uncomment log(uri_s) above and call function Sony_get_content_list() to see what they are   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
Reply


Forum Jump: