Skip to content

Instantly share code, notes, and snippets.

@sash13
Last active April 17, 2025 02:36
Show Gist options
  • Select an option

  • Save sash13/0e0a928990f9e5308b51 to your computer and use it in GitHub Desktop.

Select an option

Save sash13/0e0a928990f9e5308b51 to your computer and use it in GitHub Desktop.
control Sony bravia tv set
# info from https://github.com/shabunin/cf-sonytv/blob/master/scripts/SonyTV.js
#https://wolstenhol.me/blog/using-tasker-autovoice-yatse-and-xbmc
#http://mendelonline.be/sony/sony.txt
#https://github.com/breunigs/bravia-auth-and-remote/blob/master/send_command.sh
from wakeonlan import wol
import requests, requests.utils, pickle
import base64
import sys
import os.path
from time import sleep
import json
host = 'http://192.168.1.103'
pairUrl = '/sony/accessControl'
ircc = '/sony/IRCC'
headers = {'Content-Type': 'application/atom+xml'}
pairBody = {
"id":12,
"method":"actRegister",
"version":"1.0",
"params":[{"clientid":"iViewer:5","nickname":"iViewer","level":"private"},[{"clientid":"iViewer:1","value":"yes","nickname":"iViewer","function":"WOL"}]]
};
pairHeaders = {
'User-Agent' : 'iViewer/4',
'Content-Type': 'application/json'
};
cmdBody = '''<?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>{0}</IRCCCode>
</u:X_SendIRCC>
</s:Body>
</s:Envelope>''';
cmdHeaders = {
'Content-Type': 'text/xml; charset=utf-8',
'SOAPAction': '"urn:schemas-sony-com:service:IRCC:1#X_SendIRCC"'
};
key = {
#
# BLOCK MAIN
'POWER_OFF': 'AAAAAQAAAAEAAAAvAw==',
'ANALOG': 'AAAAAgAAAHcAAAANAw==',
'AUDIO': 'AAAAAQAAAAEAAAAXAw==',
'DISPLAY': 'AAAAAQAAAAEAAAA6Aw==',
'NEXT': 'AAAAAgAAAJcAAAA9Aw==',
'OPTIONS': 'AAAAAgAAAJcAAAA2Aw==',
'PAP': 'AAAAAgAAAKQAAAB3Aw==',
'SYNC_MENU': 'AAAAAgAAABoAAABYAw==',
'WIDE': 'AAAAAgAAAKQAAAA9Aw==',
'HDMI1': 'AAAAAgAAABoAAABaAw==',
'HDMI2': 'AAAAAgAAABoAAABbAw==',
'HDMI3': 'AAAAAgAAABoAAABcAw==',
'HDMI4': 'AAAAAgAAABoAAABdAw==',
'NUM_0': 'AAAAAQAAAAEAAAAJAw==',
'NUM_1': 'AAAAAQAAAAEAAAAAAw==',
'NUM_2': 'AAAAAQAAAAEAAAABAw==',
'NUM_3': 'AAAAAQAAAAEAAAADAw==',
'NUM_4': 'AAAAAQAAAAEAAAADAw==',
'NUM_5': 'AAAAAQAAAAEAAAAEAw==',
'NUM_6': 'AAAAAQAAAAEAAAAFAw==',
'NUM_7': 'AAAAAQAAAAEAAAAGAw==',
'NUM_8': 'AAAAAQAAAAEAAAAHAw==',
'NUM_9': 'AAAAAQAAAAEAAAAIAw==',
'UP': 'AAAAAQAAAAEAAAB0Aw==',
'DOWN': 'AAAAAQAAAAEAAAB1Aw==',
'LEFT': 'AAAAAQAAAAEAAAA0Aw==',
'RIGHT': 'AAAAAQAAAAEAAAAzAw==',
# SKIP 16-19
'OK': 'AAAAAQAAAAEAAABlAw==',
'HOME': 'AAAAAQAAAAEAAABgAw==',
'MENU': 'AAAAAgAAABoAAABhAw==', #PopUpMenu
'TOP_MENU': 'AAAAAgAAABoAAABgAw==', #PopUpMenu
'BACK': 'AAAAAgAAAJcAAAA8Aw==', #PREV
'VOL_UP': 'AAAAAQAAAAEAAAASAw==',
'VOL_DOWN': 'AAAAAQAAAAEAAAATAw==',
'MUTE': 'AAAAAQAAAAEAAAAUAw==',
'CH_UP': 'AAAAAQAAAAEAAAAQAw==',
'CH_DOWN': 'AAAAAQAAAAEAAAARAw==',
'BLUE': 'AAAAAgAAAJcAAAAkAw==',
'GREEN': 'AAAAAgAAAJcAAAAmAw==',
'RED': 'AAAAAgAAAJcAAAAlAw==',
'YELLOW': 'AAAAAgAAAJcAAAAnAw==',
'PLAY': 'AAAAAgAAAJcAAAAaAw==',
'PAUSE': 'AAAAAgAAAJcAAAAZAw==',
'STOP': 'AAAAAgAAAJcAAAAYAw==',
#'FAST_FORWARD': 36, # FF
'REWIND': 'AAAAAgAAAJcAAAAbAw==', # REW
'SKIP_FORWARD': 'AAAAAgAAAJcAAAAcAw==',
'SKIP_BACKWARD': 'AAAAAgAAAJcAAAAjAw==', # RETURN
#'RECORD': 40,
#'RECORDING_LIST': 41,
#'REPEAT': 42,
#'LIVE_TV': 43,
'EPG': 'AAAAAgAAAKQAAABbAw==', # WTF?
#'CURRENT_INFO': 45, # Current program information
#'ASPECT_RATIO': 46,
'EXT_INPUT': 'AAAAAQAAAAEAAAAlAw==', # External input
#'PIP_SECONDARY_VIDEO': 48, # WTF?
'SUBTITLE': 'AAAAAgAAAJcAAAAoAw==',
#'PROGRAM_LIST': 50, # WTF?
#'TELETEXT': 51,
#'MARK': 52,
#
# BLOCK 4xx
#'3D_VIDEO': 400,
#'3D_LR': 401,
#'DASH': 402, # '-'
#'FALSH_BACK': 403, # WTF? Previous channel?
#'FAVORITE': 404,
#'QUICK_MENU': 405,
#'TEXT_OPTION': 406,
#'AUDIO_DESCRIPTION': 407,
#'NET_CAST': 408, # same with Home menu
#'ENERGY_SAVING': 409,
#'AV_MODE': 410,
#'SIMPLINK': 411,
'EXIT': 'AAAAAQAAAAEAAABjAw==',
#'RESERVATION_PROGRAMS': 413, # WTF?
#'PIP_CH_UP': 414, # WTF?
#'PIP_CH_DOWN': 415, # WTF?
#'VIDEO_SWITCH': 416, # Switching between primary/secondary video
#'MY_APPS': 417,
#not tested:
'Replay': 'AAAAAgAAAJcAAAB5Aw==',
'Advance': 'AAAAAgAAAJcAAAB4Aw==',
'Eject': 'AAAAAgAAAJcAAABIAw==',
'Rec': 'AAAAAgAAAJcAAAAgAw==',
'ClosedCaption': 'AAAAAgAAAKQAAAAQAw==',
'Teletext': 'AAAAAQAAAAEAAAA/Aw==',
'GGuide': 'AAAAAQAAAAEAAAAOAw==',
'DOT' : 'AAAAAgAAAJcAAAAdAw==',
'Digital': 'AAAAAgAAAJcAAAAyAw==',
'BS' : 'AAAAAgAAAJcAAAAsAw==',
'CS' : 'AAAAAgAAAJcAAAArAw==',
'BSCS': 'AAAAAgAAAJcAAAAQAw==',
'Ddata': 'AAAAAgAAAJcAAAAVAw==',
'InternetWidgets': 'AAAAAgAAABoAAAB6Aw==',
'InternetVideo': 'AAAAAgAAABoAAAB5Aw==',
'SceneSelect': 'AAAAAgAAABoAAAB4Aw==',
'Mode3D' : 'AAAAAgAAAHcAAABNAw==',
'iManual' : 'AAAAAgAAABoAAAB7Aw==',
'Jump' : 'AAAAAQAAAAEAAAA7Aw==',
'MyEPG': 'AAAAAgAAAHcAAABrAw==',
'ProgramDescription': 'AAAAAgAAAJcAAAAWAw==',
'WriteChapter': 'AAAAAgAAAHcAAABsAw==',
'TrackID' : 'AAAAAgAAABoAAAB+Aw==',
'TenKey': 'AAAAAgAAAJcAAAAMAw==',
'AppliCast': 'AAAAAgAAABoAAABvAw==',
'acTVila': 'AAAAAgAAABoAAAByAw==',
'DeleteVideo': 'AAAAAgAAAHcAAAAfAw==',
'EasyStartUp': 'AAAAAgAAAHcAAABqAw==',
'OneTouchTimeRec': 'AAAAAgAAABoAAABkAw==',
'OneTouchView' : 'AAAAAgAAABoAAABlAw==',
'OneTouchRec' : 'AAAAAgAAABoAAABiAw==',
'OneTouchRecStop' : 'AAAAAgAAABoAAABjAw==',
}
def call_auth(s, pwd='', c='', wait=0.5):
if pwd:
print c
pairHeaders['Authorization'] = 'Basic '+base64.b64encode(':'+pwd)
print pairHeaders['Authorization']
r = s.post(host+pairUrl, data = json.dumps(pairBody), cookies = c, headers = pairHeaders)
if wait : sleep(wait)
return r
def call_cmd(s, cmd, c = '', wait=0.5):
print 'Try evaluate: '+key[cmd]
r = s.post(host+ircc, data = cmdBody.format(key[cmd]), cookies = c, headers = cmdHeaders)
if wait : sleep(wait)
return r
def power_on():
print 'Power on'
wol.send_magic_packet('3c:77:e6:33:6f:01', ip_address='192.168.1.103')
sleep(4)
def auth_loop(s, c):
a = ''
try:
a = json.loads(call_auth(s,'', c).text)
except requests.exceptions.ConnectionError as e:
power_on()
a = {'power':0}
return a
def call_seq(seq):
c = None
s = requests.Session()
if os.path.isfile('cookies'):
print('cookies exist')
with open('cookies') as f:
c = requests.utils.cookiejar_from_dict(pickle.load(f))
a = auth_loop(s, c)
if 'power' in a:
a = auth_loop(s, c)
print(a)
if 'error' in a and a['error'][1] in 'not power-on':
power_on()
auth_loop(s, c)
if 'error' in a and a['error'][1] in 'Unauthorized':
print(a)
pwd = raw_input('--> ')
a = call_auth(s, pwd, c)
with open('cookies', 'w') as f:
pickle.dump(requests.utils.dict_from_cookiejar(a.cookies), f)
print(a.text)
if 'result' in a:
signals = seq.split(',')
for signal in signals:
call_cmd(s, signal, c)
print 'Start auth'
call_seq('POWER_OFF')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment