The sony bravia has a HTTP API interacted with using a Pre-Shared key. There's a more complex auth flow but I've not described it here.
There wasn't any documentation, so I've written some. If you're a TV integrator don't read this, you'll laugh. I'm probably just getting confused by UPnP.
Disclaimer: I've only tested this on my TV, which is a KDL-50W829B. Your TV might not have all of the services; see Available services section for how to discover what your TV supports.
- A PDF document left searchable by Kindermann
- alanreid/bravia
- waynehaffenden/bravia
- breunigs/bravia-auth-and-remote
-
Enable 'Wake on LAN' in the TV options (Settings -> Network -> Home Network Setup -> Remote Start (switch on)
-
Send a Wake on LAN packet to the TV using standard methods, e.g.:
wakeonlan -i 192.168.0.98 FC:F1:de:ad:b3:3f
Send POST requests, with a JSON payload. An example (to list the Methods available to be called against the 'system' service) is:
curl -H "Content-Type: application/json" \
-X POST \
-d '{"id": 20, "method": "getMethodTypes", "version": "1.0", "params": [""]}' \
http://192.168.0.98/sony/system
To send authenticated requests, set a "pre-shared" key, by visiting Settings -> Network -> Home Network Setup -> IP Control -> Pre-Shared Key. Say mine was 'pass123'.
curl -H "Content-Type: application/json" \
-H "X-Auth-PSK: pass123" \
-X POST \
-d '{"id": 20, "method": "PowerOff", "version": "1.0", "params": []}' \
http://192.168.0.98/sony/system
For brevity's sake, I'll only give the endpoint, JSON, and if it's communicated, on other endpoints.
The TV has a file called 'dmr.xml' (a upnp.org schema) made available at http://192.168.0.98:52323/dmr.xml -- useful for determining the following endpoints exist on my TV:
- /sony/IRCC
- /sony/accessControl
- /sony/appControl
- /sony/avContent
- /sony/browser
- /sony/cec
- /sony/encryption
- /sony/guide
- /sony/notification
- /sony/recording
- /sony/system
- /sony/videoScreen
For each service, you can use the getVersions
or getMethodTypes
methods to
explore which methods are available on that service.
A precis of what's supported for these services is given below:
Authenticated endpoint. SOAP interaction. Suspect this is the main entrypoint for upnp systems?
Interacting with this service allows you to "fake" buttons being pressed on the
remote. This is how the bravia
npm library controls the TV.
You send this endpoint a single remote controller code -- available from the
system endpoints getRemoteControllerInfo
method, and it will execute it as if you
pressed it on your TV remote.
For reasons passing understanding (there's probably a standard for this...somewhere), you interact with this endpoint as SOAP rather than JSON, sending it this payload:
<?xml version="1.0" encoding="utf-8"?>
<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-COMMAND></IRCCCode>
</u:X_SendIRCC>
</s:Body>
</s:Envelope>
For example, to power it off, use this curl command:
curl -H "Content-Type: application/json" \
-X POST \
-H "X-Auth-PSK: pass123" \
-d '<?xml version="1.0" encoding="utf-8"?>
<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>AAAAAQAAAAEAAAAvAw=</IRCCCode>
</u:X_SendIRCC>
</s:Body>
</s:Envelope>' \
http://192.168.0.98/sony/IRCC
There appears to be additional information at http://192.168.0.98:52323/IRCCSCPD.xml which describes an additional X_GetStatus request you can use with the IRCC endpoint, providing a category code.
versions: [1.0] params
{ "uri": "string" }
empty response
versions: [1.0] params
{
"source": "string",
"type": "string",
"count": int
}
response
{
"count": int
}
versions: [1.0] params
{
"source": "string",
"type": "string",
"stIdx": int,
"cnt": int,
"type": "string",
}
response
{
"uri": "string",
"title": "string",
"index": "int",
"dispNum": "string",
"originalDispNum": "string",
"tripletStr": "string",
"programNum": "int",
"programMediaType": "string",
"startDateTime": "string",
"durationSec": "int",
"channelName": "string",
"isProtected": "bool",
"directRemoteNum": "int",
"isAlreadyPlayed": "bool"
}
versions: [1.0] params
{} //empty input
response
[
{
"title": "string",
"uri": "string",
"connection": "bool",
"label": "string",
"icon": "string"
}
]
purpose
Lists your "Inputs" on your TV, with their connection status -- it knows if
they're connected or not -- providing their title that you gave them on the
TV. Also provides a URI to identify them, to be used in <WHERE?>
versions: [1.0] standard to all services
versions: [1.0] params
{} //empty input
response
{
"ratingCountry": "string",
"ratingTypeAge": "integer",
"ratingTypeSony": "string",
"ratingCustomTypeTV": [
"string*"
],
"ratingCustomTypeMpaa": "string",
"ratingCustomTypeCaEnglish": "string",
"ratingCustomTypeCaFrench": "string",
"unratedLock": "bool"
}
versions: [1.0] params
{} // empty input
response
{
"uri": "string",
"source": "string",
"title": "string",
"dispNum": "string",
"originalDispNum": "string",
"tripletStr": "string",
"programNum": "int",
"programTitle": "string",
"startDateTime": "string",
"durationSec": "int",
"playSpeed": "string",
"bivl_serviceId": "string",
"bivl_assetId": "string",
"bivl_provider": "string",
"mediaType": "string"
}
purpose
Gives information about what's currently playing on the TV. A "Now playing"
of sorts. Limited by what the TV itself knows -- if it's on the OSD it's
returned, if not, nothing doing. Not super useful if the TV isn't the
source of your media.
versions: [1.0] params
{} // empty input
response
{
"uri": "string",
"source": "string",
"title": "string",
"dispNum": "string",
"originalDispNum": "string",
"tripletStr": "string",
"programNum": "int",
"programTitle": "string",
"startDateTime": "string",
"durationSec": "int",
"playSpeed": "string",
"bivl_serviceId": "string",
"bivl_assetId": "string",
"bivl_provider": "string",
"mediaType": "string"
}
purpose
I mean it's the same as version 1? Literally no difference? Maybe if you
had dual tuners or something?
versions: [1.0] params
{} // empty input
response
{
"scheme": "string",
}
[
"getSchemeList",
[],
[
"{\"scheme\":\"string\"}*"
],
"1.0"
],
[
"getSourceList",
[
"{\"scheme\":\"string\"}"
],
[
"{\"source\":\"string\"}*"
],
"1.0"
],
[
"getSourceList2",
[
"{\"scheme\":\"string\"}"
],
[
"{\"source\":\"string\"}*"
],
"1.0"
],
[
"getVersions",
[],
[
"string*"
],
"1.0"
],
[
"setDeleteProtection",
[
"{\"uri\":\"string\",\"isProtected\":\"bool\"}"
],
[],
"1.0"
],
[
"setFavoriteContentList",
[
"{\"favSource\":\"string\",\"contents\":\"string-array\"}"
],
[],
"1.0"
],
[
"setPlayContent",
[
"{\"uri\":\"string\"}"
],
[],
"1.0"
],
[
"setPlayTvContent",
[
"{\"channel\":\"string\"}"
],
[],
"1.0"
],
[
"setTvContentVisibility",
[
"{\"uri\":\"string\",\"epgVisibility\":\"string\",\"channelSurfingVisibility\":\"string\",\"visibility\":\"string\"}*"
],
[],
"1.0"
],
[
"getContentCount",
[
"{\"source\":\"string\",\"type\":\"string\",\"target\":\"string\"}"
],
[
"{\"count\":\"int\"}"
],
"1.1"
],
[
"getMethodTypes",
[
"string"
],
[
"string",
"string*",
"string*",
"string"
],
"1.1"
],
[
"getVersions",
[],
[
"string*"
],
"1.1"
],
[
"getContentList",
[
"{\"source\":\"string\",\"stIdx\":\"int\",\"cnt\":\"int\",\"type\":\"string\",\"target\":\"string\"}"
],
[
"{\"uri\":\"string\",\"title\":\"string\",\"index\":\"int\",\"dispNum\":\"string\",\"originalDispNum\":\"string\",\"tripletStr\":\"string\",\"programNum\":\"int\",\"programMediaType\":\"string\",\"startDateTime\":\"string\",\"durationSec\":\"int\",\"channelName\":\"string\",\"isProtected\":\"bool\",\"directRemoteNum\":\"int\",\"isAlreadyPlayed\":\"bool\"}*"
],
"1.2"
],
curl -H "Content-Type: application/json" \
-H "X-Auth-PSK: rabbits" \
-X POST \
-d '{"id": 20, "method": "getSystemSupportedFunction", "version": "1.0", "params": [""]}' \
http://192.168.0.98/sony/system
Thank you for this.
Also just found more documentation that might be useful.