waynehaffenden / bravia

Node.js module for discovering and controlling Sony BRAVIA Android TVs.
MIT License
46 stars 18 forks source link

Info for invokes #3

Closed muldy closed 7 years ago

muldy commented 7 years ago

Hi! (this is not a issue) I'm doing a express webapp to use the bravia module provided by you, I'm wondering how you know the syntax for the method calls: bravia.audio.invoke('setAudioVolume', '1.0', { target: 'speaker', volume: 50 }); Particularly the { target: 'speaker', volume: 50 } part. Is there any source for this information? I'm particularly interested in the syntax for the audio getSpeakerSettings method.

I'm planning to publish my app on github when I clean up the code.

Thanks in advance.

waynehaffenden commented 7 years ago

This was the same issue I had when writing this module and there just seems to be a lack of documentation from Sony about this.

However, the TV's actually have an API that returns all the available methods, versions, parameters and return values. You can invoke this information yourself, by calling for example bravia.audio.getMethodTypes() which will return a JSON response containing all the audio methods available for all the different versions of the API. You can also pass in a version string to the method if you just want to query the methods available for a particular API.

I found that most of the parameters and return values are fairly self explanatory but unfortunately there are some that I don't really have a clue what they mean.

There are a bunch of other "service protocols" available, that can be accessed as bravia.system.getMethodTypes() etc. The ones that are available are:

accessControl appControl audio avContent browser cec encryption guide recording system videoScreen

I should update the README to include this information as to be fair it isn't obvious if you've not got much experience with the Bravia API.

I hope this helps.

Wayne

muldy commented 7 years ago

Thanks,

Yes, I've been listing the protocols and the geMethodTypes like system: [{"version":"1.0","methods":[["getCurrentTime",[],["string"],"1.0"],["getDeviceMode",["{\"value\":\"string\"}"],["{\"isOn\":\"bool\"}"],"1.0"],["getInterfaceInformation",[],["{\"productCategory\":\"string\", \"productName\":\"string\", \"modelName\":\"string\", \"serverName\":\"string\", \"interfaceVersion\":\"string\"}"],"1.0"],["getLEDIndicatorStatus",[],["{\"mode\":\"string\", \"status\":\"string\"}"],"1.0"],["getNetworkSettings",["{\"netif\":\"string\"}"],["{\"netif\":\"string\", \"hwAddr\":\"string\", \"ipAddrV4\":\"string\", \"ipAddrV6\":\"string\", \"netmask\":\"string\", \"gateway\":\"string\", \"dns\":\"string*\"}*"],"1.0"],["getPowerSavingMode",[],["{\"mode\":\"string\"}"],"1.0"],["getPowerStatus",[],["{\"status\":\"string\"}"],"1.0"],["getRemoteControllerInfo",[],["{\"bundled\":\"bool\", \"type\":\"string\"}","{\"name\":\"string\", \"value\":\"string\"}*"],"1.0"],["getRemoteDeviceSettings",["{\"target\":\"string\"}"],["{\"target\":\"string\", \"currentValue\":\"string\", \"deviceUIInfo\":\"string\", \"title\":\"string\", \"titleTextID\":\"string\", \"type\":\"string\", \"isAvailable\":\"Boolean\", \"candidate\":\"GeneralSettingsCandidate[]\"}*"],"1.0"],["getSystemInformation",[],["{\"product\":\"string\", \"region\":\"string\", \"language\":\"string\", \"model\":\"string\", \"serial\":\"string\", \"macAddr\":\"string\", \"name\":\"string\", \"generation\":\"string\", \"area\":\"string\", \"cid\":\"string\"}"],"1.0"],["getSystemSupportedFunction",[],["{\"option\":\"string\", \"value\":\"string\"}*"],"1.0"],["getWolMode",[],["{\"enabled\":\"bool\"}"],"1.0"],["requestReboot",[],[],"1.0"],["setDeviceMode",["{\"value\":\"string\", \"isOn\":\"bool\"}"],[],"1.0"],["setLanguage",["{\"language\":\"string\"}"],[],"1.0"],["setPowerSavingMode",["{\"mode\":\"string\"}"],[],"1.0"],["setPowerStatus",["{\"status\":\"bool\"}"],[],"1.0"],["setWolMode",["{\"enabled\":\"bool\"}"],[],"1.0"],["getMethodTypes",["string"],["string","string*","string*","string"],"1.0"],["getVersions",[],["string*"],"1.0"]]},{"version":"1.1","methods":[["getCurrentTime",[],["{\"dateTime\":\"string\", \"timeZoneOffsetMinute\":\"int\", \"dstOffsetMinute\":\"int\"}"],"1.1"],["setLEDIndicatorStatus",["{\"mode\":\"string\", \"status\":\"string\"}"],[],"1.1"]]}]

Ok, so for the actual method parameters is just a best guess :)

waynehaffenden commented 7 years ago

Yeah sadly, if you manage to find some documentation then please come back and let me know :)

ilessiivi commented 7 years ago

You're both on the right tracks - the documentation is there in the getMethodTypes queries. If you look at the setAudioVolume method definition in the audio.getMethodTypes() response:

["setAudioVolume", [{
    "target": "string",
    "volume": "string"
}], ["int"], "1.0"]

The volume needs to be given as a string and not as an integer. Int is what the setAudioVolume query would return (it returns a 0 for me, even when the query succeeds instead of anything meaningful...). Here's a pull request to fix the demo in readme: #4

How does the getSpeakerSettings method work then? Checking the getMethodTypes, a target string is needed:

["getSpeakerSettings", [{
    "target": "string"
}], [{
    "target": "string",
    "currentValue": "string",
    "deviceUIInfo": "string",
    ...
}*], "1.0"]

First I tried speaker and headphone as the target but those return an "Illegal Argument" error. By trial and error I figured out that querying it with an empty object {} as the params gets us the possible targets:

bravia.audio.invoke("getSpeakerSettings", "1.0", {}).then(function(info) {
    console.log("speaker settings", info);
}).catch(function(err) {
    console.error("speaker settings err", err);
});
[{
    "target": "tvPosition",
    "currentValue": "tableTop"
}, {
    "target": "subwooferLevel",
    "currentValue": "17"
}, {
    "target": "subwooferFreq",
    "currentValue": "8"
}, {
    "target": "subwooferPhase",
    "currentValue": "normal"
}, {
    "target": "subwooferPower",
    "currentValue": "on"
}]

I wish there was an actual documentation for this stuff but I guess Github comments will have to do 😄

waynehaffenden commented 7 years ago

Awesome, thank you for experimenting and fixing the documentation. Maybe, we can start a wiki on this and try and complete as much documentation on the API as we can, thoughts?

P.S. I don't have access to a Bravia TV as originally wrote this library for a friend, can get the odd access but won't make this very easy for me to do on my own but with you guys contributions I think it's certainly possible!

AmigaZoid commented 7 years ago

Just wanted to let you know, the help file on NPM still says volume: 50 instead of '50'.

One question: When I try to getMethodTypes(), I end up with this instead of actual types.

[ { version: '1.0', methods: [ [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object] ] }, { version: '1.1', methods: [ [Object], [Object] ] } ]

I'm still fairly new to node js, any direction you can give me to get the actual list would be great. Everything else is working great. Thanks for your work.

waynehaffenden commented 7 years ago

I'm just testing another update to the code so once this is done I'll push the latest changes to NPM.

You'll need to use util.inspect(). See util.inspect()

AmigaZoid commented 7 years ago

I don't know if having a sony subwoofer and soundbar hooked up changes anything but this is what I've figured out. Everything works for me except changing the volume. I have everything else voice controlled by an amazon echo. I can change volume level to 'speaker' and when I get the value, it is where I set it. The TV does not actually change volume on hdmi1 but I did notice that it IS changing the volume on the home screen.

muldy commented 7 years ago

I was hoping that the setSpeakerSettings would be corresponding to the operation pressing: Action Menu -> Speakers -> Tv Speakers/Audio System. I would like to automate this...

AmigaZoid commented 7 years ago

Confirmed. After turning off the sound bar, changing the sound works perfectly. I just need to figure out how to change the connected audio which we normally control with the normal tv remote.

waynehaffenden commented 7 years ago

What does the following return as @ilessiivi wrote above:

bravia.audio.invoke("getSpeakerSettings", "1.0", {}).then(function(info) {
    console.log("speaker settings", info);
}).catch(function(err) {
    console.error("speaker settings err", err);
});
muldy commented 7 years ago

This: speaker settings [ { target: 'tvPosition', currentValue: 'wallMount' }, { target: 'subwooferLevel', currentValue: '17' }, { target: 'subwooferFreq', currentValue: '8' }, { target: 'subwooferPhase', currentValue: 'normal' }, { target: 'subwooferPower', currentValue: 'on' } ]

waynehaffenden commented 7 years ago

You've probably already tried it but just interested to know that if you invoke the setAudioVolume method using one of the targets you got back i.e. 'subwooferLevel' if that changes the volume level for it or not?

muldy commented 7 years ago

I think somewhere in the TV settings there is a option to connect a subwoofer to the headphones jack ... So the subwoofer levels must be for that option? I think I've tried reading these values, when I change from Tv speakers to Audio system and see no change in them...

muldy commented 7 years ago

Maybe some target parameter gets the Audio System levels...

AmigaZoid commented 7 years ago

The whole issue for me is HDMI-CEC. Is it possible to send a command that talks to the Sony HDMI/ARC? I get almost identical results from getspeakersettings as muldy. The soundbar volume can be controlled by it's own remote or by the bravia remote which makes me wonder if there is a way to send the volume command to CEC. I've tried changing subwoofer and also the headphone settings which don't have any results.

JamesScammell commented 7 years ago

Hi, It was myself and Wayne that started investigating this some months ago, we are currently testing again, unfortunately I am unable to fully test the audio setup you guys have as I am currently using a sound bar connected via Optical so no ARC.

I think the best way to try and move this on will be to install the TV & Video sidesview app (official Sony app) on an IOS or Android device and try changing the volume and see if that adjusts it, if it does we can look into packet capturing.

Also worth checking the home theatre control settings, I have no idea what options there are as It obviously doesn't detect arc but this may have some useful settings

muldy commented 7 years ago

I'm using a Yamaha 5.1(Without ARC) system through optical cable too. For normal Tv usage I don't turn on the Yamaha amplifier, but when I see movies, I turn the Amp on, switch to HDM1... and I have to set the speakers settings to Audio system... and when I'm done I have to put it back to the TV speakers (YAWWN). This is because With Kodi on android I can't get DTS audio out of the Optical, so I use a raspberry pi...

waynehaffenden commented 7 years ago

@muldy Me and James are playing around with his TV as we speak to see if we can help crack it for you. Interestingly enough calling the API method: audio.getSoundSettings method which is on version 1.1 seems to give back whether it's on speaker or audioSystem, although, for us seems to be back to front. Can you try on yours and see what you get back.

waynehaffenden commented 7 years ago

@muldy It seems that changing the speaker mode between TV and Audio System is most likely possible using the audio.setSoundSettings method, however, sadly we cannot work out what is meant by GeneralSettings[], can only assume the parameter would look something like:

{ "settings": [
  { ... } // <-- Unknown what goes in this "GeneralSettings" object.
] }

We've tried a bunch of these but everything gives back an illegal argument error and surprise, surprise not once ounce of documentation anywhere available on it...

waynehaffenden commented 7 years ago

@AmigaZoid What happens if you invoke:

bravia.audio.invoke("getVolumeInformation", "1.0", {}).then(function(info) {
    console.log(info);
}).catch(function(err) {
    console.error(err);
});

I'm interested to know whether you have more than just speaker and headphone as targets.

JamesScammell commented 7 years ago

I have emailed Sony support to see if they will give us API documentation, will update when I have one.

AmigaZoid commented 7 years ago

Please let me know if you figure it out. I'm in the process of a OS reinstall so will try the command above once I have Node reinstalled.

waynehaffenden commented 7 years ago

@AmigaZoid I most certainly will do that will be really useful for me. When you have completed your project, would this be something you would be willing to share as I know my friend (who I originally wrote this module for) is looking to do exactly the same as you and he isn't a programmer and I don't have much time to help him. Also, when you have reinstalled your OS and have some time let us know what results you get back from the getVolumeInformation method as this may hold the answer.

I have now created a new issue for what all of us here are really after. You can find it here.

AmigaZoid commented 7 years ago

[ { target: 'speaker', volume: 2, mute: false, maxVolume: 100, minVolume: 0 }, { target: 'headphone', volume: 26, mute: false, maxVolume: 100, minVolume: 0 } ]

Same info I had before for getspeakersettings

As for the alexa setup, sure I can share. It's really minimal code for the way I am achieving it. I have a normal Alexa app and lambda that is going through AWS.Iot. So I have a subscribe/publish setup through iot that simply post a word like TVPower or VolumeUP to the Node server. I simply use an if or a switch to send the bravia code through your script to the TV. I'm doing the same thing for Kodi except I'm sending a JSON with http to the kodi webserver. Planning on adding zwave lights also if I can get it running.

JamesScammell commented 7 years ago

Project 2 is lightening for us but Wayne will also use them so easier to test. Would be interested to know if u are running Kodi natively on theTv (I currently am) of using an external device.

AmigaZoid commented 7 years ago

Yes, running kodi on the TV without an external box.

JamesScammell commented 7 years ago

Good to know, Sony's response was basically that they don't provide technical spec to end users which was what we expected, doesn't hurt to ask just great you stumbled on that documentation which should help a lot, just about to look now.

AmigaZoid commented 7 years ago

Found an app that the volume control changes the TV and soundbar just like the sony remote. I'll do some sniffing.

AmigaZoid commented 7 years ago

Ok so I finally found time to check out the app and used a packet sniffer to examine the commands. It's the standard volumeUp and volumeDown IRCC codes. I testing them by sending the commands and they work.

If you know of an app that allows setting volume at 50% etc., please pass it along. For now I'll just build some loops to raise volume by 10 etc.

JamesScammell commented 7 years ago

Just to confirm using the volume in the ircc changes volume on external devices via arc but the one in the other method simply changes the volume on the TVs but not external arc controlled devices, that seems pretty strange.

AmigaZoid commented 7 years ago

using Bravia.send('VolumeUp') or volume down works perfectly but when using an amazon echo, I wanted a quicker way to raise the volume so I tried ... bravia.audio.invoke('setAudioVolume', '1.0', { target: 'speaker', volume: '50' }); This command has no effect on the volume for the TV on HDMI 1 with Dish Network or the sony connected soundbar. It does however affect the volume on the android app home screen.

To get around this with the amazon echo, I simply created a loop so I can ask alexa to raise the volume by 23 etc. If I don't supply a value, it raises or lowers the volume by 5.

JamesScammell commented 7 years ago

ok, If I'm understanding correctly ideally you just want to set the speaker volume to 50 so it is set regardless of what it currently is but simply specifying that doesn't have any impact I wonder if a function to be created that gets the volume status and then involves the vol up or vol down and sends the value accordingly, would have to get Wayne's opinion to see how doable that is.

JamesScammell commented 7 years ago

@AmigaZoid, I have finally had some time to sit down and look through the documentation and found the below, have you tried leaving the target blank, I just tried it and for me it does the same thing as setting the speaker as target (my external audio device has no CEC intelligence) If you haven't already could you try {"target":"", "volume":"50"}

Snippet from the documentation target string 1   Output target of sound. Following values are defined. "" - output sound to all output equipment that device has. if mute information of all output is common, this value is set. "speaker" - output sound to speaker "headphone" - output sound to headphone

AmigaZoid commented 7 years ago

The volume bar on the TV shows for a couple of seconds but there is no change to the volume. Stays at the same number.

mschwartz commented 7 years ago
'getDeviceMode',
    [ '{"value":"string"}' ],
    [ '{"isOn":"bool"}' ],
    '1.0' ],
            try {
                this.deviceMode = await this.client.system.invoke('getDeviceMode', '1.0', {})
            }
            catch (e) {
                debug(this.device, e)
            }
            try {
                this.deviceMode = await this.client.system.invoke('getDeviceMode', '1.0', {value: '*'})
                debug(this.deviceMode)
            }
            catch (e) {
                    debug(this.device, e)
            }
  BraviaHost sony-810c Error: Illegal Argument
  at bravia._request.then.response (/Users/mschwartz/hosts/bigmoney/github/mschwartz/ha2/node_modules/bravia/src/service-protocol.js:61:18)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:169:7) +2s
  BraviaHost sony-810c Error: Illegal JSON

  BraviaHost sony-810c Error: Illegal Argument
    at bravia._request.then.response (/Users/mschwartz/hosts/bigmoney/github/mschwartz/ha2/node_modules/bravia/src/service-protocol.js:61:18)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:169:7) +31ms
mschwartz commented 7 years ago

It wants "value":"string" as argument. Any idea what it really wants? :)

JamesScammell commented 7 years ago

The document gives the information below, could you explain what you are using this for, it isn't a method I have previously attempted to use so just curious.

The following does give the status back on mine {"value":"shop"} it can be changed with the set using {"value":"shop", "isOn":bool} not sure if there is any other available modes.

params' Elements An object composed by following pair(s). name type multiplicity default description value string 1   Device mode value which you want to know the status. "shop" - mode suitable for shop. JSON Example { "id": 25, "method": "getDeviceMode", "params": [{"value": "shop"}], "version": "1.0" }

mschwartz commented 7 years ago

I see.

I was investigating a way to find out what is on the TV. Is it playing a Netflix stream? YouTube? Or TV. Is it set to HDMI 1?

And so on.

shop mode must be for display at the store, disable or enable various functionality. That's my guess.

I wanted to note that {} as argument doesn't list the modes for me.

What document? I must be blind or something :)

JamesScammell commented 7 years ago

{} just throws an illegal argument for me too, it isn't you it's the api, someone kindly linked to the official Sony document which is not publicly available but I kept a copy. Legally we can't publish it some of it still doesn't fully explain and requires updating based on findings, there is an open issue at https://github.com/waynehaffenden/bravia/issues/6 For the api documentation but no ones offered and we are struggling to find the time.

I will have a look and see if I can find any method to achieve what you are trying later I can only think of one that lists running app and current input so may require querying both to get the end result will see what I can do when I get a chance.

I think shop mode kind of optimises display and sound for a shop type envireoment rather than the home, that's an assumption on my part not definitive.

mschwartz commented 7 years ago

I've been exploring the APIs with getMethods() on each of the protocols enumerated in the Bravia instance. Some of them look quite promising.

There's one that returns a list of all the apps with icon/url for images and everything. A method to start one of those, it seems, too. But querying for the active app doesn't show anything when I start netflix from the remote control.

Also, I am polling the TV for volume and power state every 500ms. It's silly they don't have a web socket for that kind of thing (like LG WbOS 3 does). I tried polling faster (so the UI is more responsive), but was getting some http failures (ECONNTIMEOUT) fetching the volume info.

JamesScammell commented 7 years ago

yeah no web sockets that I am aware of, just had a look and there is one about playing content but not sure if it will be usefull seems to be largely related to pulling data from the TVs internal tuners.

mschwartz commented 7 years ago

Really? I haven't found any way to detect if the TV is showing HDMI1, or playing Netflix or whatever.

It'd be awesome to be able to tell if Netflix is playing, paused, the title of the show, etc., too.

Here's the latest. I was able to configure some favorites (in my code/app, not the TV) for various apps. See them on the right:

image

The API gives me the icons and uri to launch each, and all that works.

JamesScammell commented 7 years ago

Do you have a method for avContent:1.0:getPlayingContentInfo, I haven't done much in the way of testing but for example I currently have my external Satellite tuner on HDMI 4 and it outputs the following

object uri: "extInput:hdmi?port=4" source: "extInput:hdmi" title: "HDMI 4/ARC"

I have attached the taken screen shots from the documentation, I will be removing shortly but put it there for your reference. Please let me know how you get on, I am not sure this can interact with the apps themselves but would be awesome.

mschwartz commented 7 years ago

I get an exception, "bad state" when the TV is playing Netflix.

Does it work for you?

mschwartz commented 7 years ago

I'd love to get my hands on this doc :)

JamesScammell commented 7 years ago

I have sent it over, as I mentioned in the email I can't remove you email from your post so please do so at your earliest convenience.

I haven't tested the Netflix bit yet, just off to play some football, will try and do tonight if I get a chance other wise will be later on in the week.

mschwartz commented 7 years ago

Thank you so much!

Though I haven't received the email yet.

JamesScammell commented 7 years ago

Shared via Google drive

casenjo commented 7 years ago

Hi! I'm working on a Kodi plugin to do various things with my Bravia TV and have been having trouble finding proper documentation as well. Would it be possible for someone to share that doc with me as well? It'd be much appreciated :)