Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing support for devices without getSupportedApiInfo (Sony BDV-N5200, HAP-S1, BDV-N9200W) #29

Open
wouzzie opened this issue Sep 16, 2018 · 37 comments

Comments

@wouzzie
Copy link

wouzzie commented Sep 16, 2018

Hi,

For the past few days, i'm trying to get your project to control my Sony BDV-N5200. But somehow, i can't get it to work. Installation on my Raspberry Pi and discovering the endpoint was all straightforward, but actually trying to control my device got me stuck on an error message i can't figure out:

Setting debug level to 3
DEBUG:root:Using endpoint http://192.168.2.189:10000/sony
DEBUG:songpal.device:Endpoint: http://192.168.2.189:10000/sony
DEBUG:songpal.device:Guide endpoint: http://192.168.2.189:10000/sony/guide
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): 192.168.2.189:10000
DEBUG:urllib3.connectionpool:http://192.168.2.189:10000 "POST /sony/guide HTTP/1.1" 200 43
DEBUG:songpal.device:Got getSupportedApiInfo: {'error': [12, 'getSupportedApiInfo'], 'id': 1}
Traceback (most recent call last):
  File "/usr/local/bin/songpal", line 11, in <module>
    sys.exit(cli())
  File "/home/pi/.local/lib/python3.5/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/home/pi/.local/lib/python3.5/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/home/pi/.local/lib/python3.5/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/pi/.local/lib/python3.5/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/pi/.local/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/home/pi/.local/lib/python3.5/site-packages/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args[1:], **kwargs)
  File "/home/pi/.local/lib/python3.5/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/home/pi/.local/lib/python3.5/site-packages/songpal/main.py", line 29, in wrapper
    return loop.run_until_complete(f(*args, **kwargs))
  File "/usr/lib/python3.5/asyncio/base_events.py", line 466, in run_until_complete
    return future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/pi/.local/lib/python3.5/site-packages/songpal/main.py", line 372, in sysinfo
    click.echo(await dev.get_system_info())
  File "/home/pi/.local/lib/python3.5/site-packages/songpal/device.py", line 174, in get_system_info
    return Sysinfo.make(**await self.services["system"]["getSystemInformation"]())
KeyError: 'system'

Whichever command i try, i get the same error message. Any help or a guide in the right direction is highly appreciated!

@rytilahti rytilahti changed the title Error connecting to device Error connecting to device (Sony BDV-N5200) Sep 16, 2018
@rytilahti rytilahti changed the title Error connecting to device (Sony BDV-N5200) Error connecting to device (Sony BDV-N5200, non-existing getSupportedApiInfo) Sep 16, 2018
@rytilahti
Copy link
Owner

The error code (12) indicates a non-existing method which is documented here: https://developer.sony.com/develop/audio-control-api/api-references/api-overview-2#_getsupportedapiinfo_v1_0 -- Unfortunately I don't really have a quick solution for that at this point, as this call is used to locate what services is being provided and where their endpoints are.

Maybe it is using websockets also instead of xhrpost? What is the output from discovery? Does it list services? You could try songpal -dd discover (or fetch the description file otherwise) to see if the XML file contains some extra hints how to command the device.

I think you best bet would be capturing the network traffic and trying to see how the songpal app is calling that method.

rytilahti added a commit that referenced this issue Sep 17, 2018
Error out in CLI if unable to fetch the API information as seen in #29
@wouzzie
Copy link
Author

wouzzie commented Sep 19, 2018

Thanks for your fast reply! Discovery is listing some services, i recall at least audio and system tot be among them. i'll post the full output and XML-code when i'm back home tomorrow.

@wouzzie
Copy link
Author

wouzzie commented Sep 26, 2018

Hi,

Bit later than expected, but i managed to pull some info from my home cinema system. The output of songpal discover is as follows:

Discovering for 3 seconds

Found BDV-N5200W - BDV-2014
* API version: 1.0
* Endpoint: http://192.168.2.189:10000/sony
* Services:
  - Service: guide
  - Service: system
  - Service: illumination
  - Service: audio

Below are the output of songpal -dd discover and the XML-file i pulled from my system:
bdv-nv-ms-xml.txt
songpal-discover.txt

I tried to use Wireshark to get more info on the system control trough songpal, but it didn't gave any clues yet. But i'll keep digging!

@rytilahti
Copy link
Owner

Ok, those look perfectly fine to me. So I suppose you'll really need to do some wireshark sniffing to see what the official app does to find out what's wrong there. Btw, could you also run songpal dump_devinfo BDV-N5200.json and create a PR for that file (inside devinfos/)?

@toams
Copy link

toams commented Nov 17, 2018

hello, I've got the same problem with this BDV-N5200 device. But running songpal dump_devinfo BDV-N5200.json doesnt create a file, it just outputs:

Traceback (most recent call last):
  File "/usr/local/bin/songpal", line 11, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 1134, in invoke
    Command.invoke(self, ctx)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/songpal/main.py", line 29, in wrapper
    return loop.run_until_complete(f(*args, **kwargs))
  File "/usr/lib/python3.6/asyncio/base_events.py", line 468, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.6/dist-packages/songpal/main.py", line 110, in cli
    await x.get_supported_methods()
  File "/usr/local/lib/python3.6/dist-packages/songpal/device.py", line 82, in get_supported_methods
    response = await self.request_supported_methods()
  File "/usr/local/lib/python3.6/dist-packages/songpal/device.py", line 75, in request_supported_methods
    return await self.create_post_request("getSupportedApiInfo", {})
  File "/usr/local/lib/python3.6/dist-packages/songpal/device.py", line 56, in create_post_request
    prepreq = req.prepare()
  File "/usr/lib/python3/dist-packages/requests/models.py", line 259, in prepare
    hooks=self.hooks,
  File "/usr/lib/python3/dist-packages/requests/models.py", line 305, in prepare
    self.prepare_url(url, params)
  File "/usr/lib/python3/dist-packages/requests/models.py", line 379, in prepare_url
    raise MissingSchema(error)
requests.exceptions.MissingSchema: Invalid URL '/sony/guide': No schema supplied. Perhaps you meant http:///sony/guide?


I'll see if i can find some more clues using wireshark

@rytilahti
Copy link
Owner

What does the discovery say or is this coming from it? Looks like there is no URL at all, so that's why it fails.

@toams
Copy link

toams commented Nov 19, 2018

I used following command: songpal --endpoint 192.168.0.100 dump-devinfo BDV-N5200.json
songpal discover gives:

Discovering for 3 seconds
Found BDV-N5200W - BDV-2014
* API version: 1.0
* Endpoint: http://192.168.0.100:10000/sony
* Services:
  - Service: guide
  - Service: system
  - Service: illumination
  - Service: audio

as output

@rytilahti
Copy link
Owner

You have to use the endpoint URL as shown by discover. So songpal --endpoint http://192.168.0.100:10000/sony dump-devinfo BDV-N5200.json would be the correct command.

@toams
Copy link

toams commented Dec 2, 2018

running songpal --endpoint http://192.168.0.100:10000/sony dump-devinfo BDV-N5200.json gives: Error: Got unexpected extra argument (BDV-N5200.json).

running the same command without BDV-N5200.json gives following output:

Traceback (most recent call last):
  File "/usr/local/bin/songpal", line 11, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/songpal/main.py", line 29, in wrapper
    return loop.run_until_complete(f(*args, **kwargs))
  File "/usr/lib/python3.6/asyncio/base_events.py", line 473, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.6/dist-packages/songpal/main.py", line 577, in dump_devinfo
    res = {'supported_methods': {k: v.asdict() for k, v in methods.items()},
AttributeError: 'NoneType' object has no attribute 'items'

@rytilahti
Copy link
Owner

You can try to run it with -d flag (it willd isplay a lot of debug output), but the problem is that for some reason it cannot download the list of available actions. So in order to debug this someone needs to use wireshark (filter with tcp port 10000) to see how the app itself communicates with the device, to find a clue why it isn't working (maybe the device requires a header we are missing?).

@toams
Copy link

toams commented Dec 22, 2018

Running with the -d flag doesnt give many useful output, so I tried running the app while logging with wireshark. I attached the resulting pcapng file.
songpal2.pcapng.zip

@toams
Copy link

toams commented Dec 22, 2018

After looking into the sourcecode I noticed there is a higher debug lvl, so I tried running with -dd flag. Now I got more useful debug output:

songpal -dd --endpoint http://192.168.0.100:10000/sony/guide dump-devinfo
Setting debug level to 2

DEBUG:root:Using endpoint http://192.168.0.100:10000/sony/guide
DEBUG:songpal.device:Endpoint: http://192.168.0.100:10000/sony/guide
DEBUG:songpal.device:Guide endpoint: http://192.168.0.100:10000/sony/guide
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): 192.168.0.100
DEBUG:urllib3.connectionpool:http://192.168.0.100:10000 "POST /sony/guide HTTP/1.1" 200 43
DEBUG:songpal.device:Got getSupportedApiInfo: {'error': [12, 'getSupportedApiInfo'], 'id': 1}
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): 192.168.0.100
DEBUG:urllib3.connectionpool:http://192.168.0.100:10000 "POST /sony/guide HTTP/1.1" 200 43
DEBUG:songpal.device:Got getSupportedApiInfo: {'error': [12, 'getSupportedApiInfo'], 'id': 2}
Traceback (most recent call last):
  File "/usr/local/bin/songpal", line 11, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/songpal/main.py", line 29, in wrapper
    return loop.run_until_complete(f(*args, **kwargs))
  File "/usr/lib/python3.6/asyncio/base_events.py", line 473, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.6/dist-packages/songpal/main.py", line 577, in dump_devinfo
    res = {'supported_methods': {k: v.asdict() for k, v in methods.items()},
AttributeError: 'NoneType' object has no attribute 'items'

According to sony's api reference error code 12 means "no such method". So it looks like this device doesnt support the "getSupportedApiInfo" call.

@rytilahti
Copy link
Owner

Indeed, it looks like there is no way to automatically obtain the API information, but that even the app uses some hardcoded information. I'll try to find some time during the holidays to look into if I can somehow easily add support for using hardcoded interfaces.

@rytilahti rytilahti changed the title Error connecting to device (Sony BDV-N5200, non-existing getSupportedApiInfo) Missing support for devices without getSupportedApiInfo (Sony BDV-N5200, HAP-S1) Oct 10, 2019
@rytilahti
Copy link
Owner

Another device without getSupportedApiInfo:

./songpal discover
Discovering for 5 seconds
INFO:songpal.discovery:Discovering for 5 seconds
ERROR:songpal.discovery:Unable to find X_ScalaerWebAPI_DeviceInfo

Found HAP-S1 - None
* API version: 1.0
* Endpoint: http://192.168.2.240:60200/sony
  Services:
    - Service: guide
    - Service: system
    - Service: audio
    - Service: avContent

[UPnP]
* URL: http://192.168.2.240:60100/hap.xml
* UDN: uuid:00000000-0000-1010-8000-uid-removed
  Services:
    - Service: urn:schemas-sony-com:service:ScalarWebAPI:1
    - Service: urn:schemas-sony-com:service:MusicConnect:1

@broglep
Copy link

broglep commented Sep 30, 2020

I'm having the same issue with BDV-N9200W - BDV-2014.

Would it be possible to use the existing devinfos files when getSupportedApiInfo is not available?

@rytilahti rytilahti changed the title Missing support for devices without getSupportedApiInfo (Sony BDV-N5200, HAP-S1) Missing support for devices without getSupportedApiInfo (Sony BDV-N5200, HAP-S1, BDV-N9200W) Sep 30, 2020
@rytilahti
Copy link
Owner

The plan was to allow injecting an existing api info manually, but alas I haven't found any time to implement that. I got sidetracked on refactoring the codebase to improve the API to consist of separate services (to follow structure used by devices) to make it more testable and my plan was to include this there (as it could be useful for tests, too), and alas, I didn't find time to finish that.

Considering that there are some potential users for this feature, I'll give it a second shot to see if I can find an easy way to implement it without any major refactoring.

@rytilahti
Copy link
Owner

@broglep are you sure the device doesn't have that API? The device info dump was contributed in this PR, so I'm wondering how that happened: #53

@broglep
Copy link

broglep commented Oct 6, 2020

@rytilahti pretty sure yes. Maybe has a newer firmware version that does not support that method anymore?

here is a trace I did capture

POST /sony/guide HTTP/1.1
Host: <redacted>:10000
Content-Type: application/json
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Python/3.8 aiohttp/3.6.2
Content-Length: 76

{"method": "getSupportedApiInfo", "params": [{}], "id": 1, "version": "1.0"}

HTTP/1.1 200 OK
Connection: close
Content-Length: 43
Content-Type: application/json

{"error":[12,"getSupportedApiInfo"],"id":1}

I did try Sony | Music Center app, and it allows to control the device, but did not yet have time to capture the communication between app and the sony device

But now as you mentioned this, I can see and try to remove guide from the discovery, maybe only guide does not support that api and the others like system & audio would. According to the sony doc, guide is the correct lib that should have that method

rytilahti added a commit that referenced this issue Oct 6, 2020
Some devices do not support the ability to obtain information about available APIs.
This PR adds new --devinfo-file option that allows using an existing devinfo file to feed the list of available services,
which may be helpful for such devices as long as they implement getMethodTypes() call for the services.

Potential fix for #29
@rytilahti
Copy link
Owner

rytilahti commented Oct 6, 2020

I just created a PR to potentially fix this, to use, simply call songpal --devinfo-file <some json file inside devinfos directory in this repo> status. It will use that file only to figure out the communication protocol and the name of the services, which are then used to try to find the available methods. This may or may not work, so please try it out and let me know what happened :-)

I think I could also add --services option to allow simply listing the services (or use the discovery response) that should be tried, but this should work for now for testing. If the device you chose does not list the protocols, you'll get Unable to get supported methods: No known protocols for audio, got: []: None, but you can force the used protocols by using either --websocket or --post.

@broglep
Copy link

broglep commented Oct 6, 2020

@rytilahti great thanks. I did try it out. I get one step further, but looks like my BDV-N9200W is actually different compared to the devinfo in this repo. E.g. the method getVolumeInformation is missing on my device whereas the devinfo has it listed

POST /sony/audio HTTP/1.1
Host: <redacted>:10000
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Python/3.8 aiohttp/3.6.2
Content-Length: 71
Content-Type: application/json

{"method": "getMethodTypes", "params": [""], "version": "1.0", "id": 1}

HTTP/1.1 200 OK
Connection: close
Content-Length: 357
Content-Type: application/json

{"id":1,"results":[["getMethodTypes",["string"],["string","string*","string*","string"],"1.0"],["getSoundSettings",["{\"target\":\"string\"}"],["{\"target\":\"string\", \"currentValue\":\"string\", \"candidate\":\"Candidate[]\"}*"],"1.0"],["getVersions",[],["string*"],"1.0"],["setSoundSettings",["{\"target\":\"string\", \"value\":\"string\"}"],[],"1.0"]]}

@rytilahti
Copy link
Owner

Good news is that it has the getMethodTypes API, bad news is that maybe they changed the volume control API completely.

Try songpal sound to see what sound settings there are available, maybe the volume is contained in there :-)

@broglep
Copy link

broglep commented Oct 6, 2020

👍 I'll dig a bit deeper tomorrow and try out the different things. And probably try to get a trace on what the sony app is doing to figure out what has changed

sound output looks like this:

ERROR:songpal.service:Got error when fetching sigs: [404, 'Not Found']
WARNING:songpal.device:Unable to create service avContent
* None (clearAudio, value: off, type: None)
  - ON (on)
* None (soundField, value: standard, type: None)
  - Music (Standard) (standard)
  - Music (Rock) (rock)
  - Music (Hip Hop) (hiphop)
  - Music (Electronica) (electronica)
  - Movie (movie)
  - Game (game)
  - Digital Music (compressionMusic)
  - Night (night)
* None (footballMode, value: off, type: None)
  - Narration ON (on)
  - Narration OFF (on_narrationOff)
  - OFF (off)
* None (digitalMusicArena, value: off, type: None)
  - ON (on)
  - OFF (off)
* None (philharmonicHall, value: off, type: None)
  - ON (on)
  - OFF (off)
* None (cinemaStudio, value: off, type: None)
  - ON (on)
  - OFF (off)

and list-all

WARNING:songpal.device:Forcing protocol ProtocolType.XHRPost
ERROR:songpal.service:Got error when fetching sigs: [404, 'Not Found']
WARNING:songpal.device:Unable to create service avContent

Service audio
  getMethodTypes
  getSoundSettings
  getVersions
  setSoundSettings

Service guide
  getMethodTypes
  getServiceProtocols
  getVersions

Service system
  getInterfaceInformation
  getMethodTypes
  getNetworkSettings
  getSettingsTree
  getVersions
  getPowerStatus
  setPowerStatus

@rytilahti
Copy link
Owner

rytilahti commented Oct 6, 2020

Yeah, looks like no volume control there, so the best approach is to look what the app is doing... Maybe the audio response is incomplete and it would actually support the volume controls, if they were hardcoded?

Looking at the sound output, option clearAudio is missing off even when it says it's the active setting, so there's definitely something wrong with that firmware...

I think I have to adapt the PR simply to allow defining --services with the list of wanted services to try out, but adding proper support for different API for volume controls etc. would need some more work than I thought it would :( But I assume other commands (besides volume control) should work now? Could you paste what does songpal discover report back as available services?

edit: one other thing you could do is to try what songpal settings returns, it uses getSettingsTree (iirc) to list all available settings.

@broglep
Copy link

broglep commented Oct 6, 2020

yes maybe they are not returning everything, or it somehow moved elsewhere

here is the output for the disvoer

INFO:songpal.discovery:Discovering for 5 seconds

Found BDV-N9200W - BDV-2014
* API version: 1.0
* Endpoint: http://<redacted>:10000/sony
  Services:
    - Service: guide
    - Service: system
    - Service: illumination
    - Service: audio

[UPnP]
* URL: http://<redacted>:64321/bdv-nv-ms.xml
* UDN: uuid:00000001-0000-1010-8000-<redacted>
  Services:
    - Service: urn:schemas-upnp-org:service:ContentDirectory:1
    - Service: urn:schemas-upnp-org:service:ConnectionManager:1
    - Service: urn:schemas-sony-com:service:ScalarWebAPI:1

getSettringsTree returns slightl different format than the code expects:

POST /sony/system HTTP/1.1
Host: <redacted>:10000
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Python/3.8 aiohttp/3.6.2
Content-Length: 83
Content-Type: application/json

{"method": "getSettingsTree", "params": [{"usage": ""}], "version": "1.0", "id": 5}

HTTP/1.1 200 OK
Connection: close
Content-Length: 1234
Content-Type: application/json

{"id":5,"result":[[{"children":[{"children":null,"isAvailable":true,"target":"audio/SoundSettings/clearAudio","title":"ClearAudio+","type":"booleanTarget"},{"children":null,"isAvailable":true,"target":"audio/SoundSettings/soundField","title":"Sound Field","type":"enumTarget"},{"children":null,"isAvailable":true,"target":"audio/SoundSettings/footballMode","title":"Football Mode","type":"enumTarget"},{"children":null,"isAvailable":true,"target":"audio/SoundSettings/digitalMusicArena","title":"Music Arena","type":"booleanTarget"},{"children":null,"isAvailable":true,"target":"audio/SoundSettings/philharmonicHall","title":"Philharmonic Hall","type":"booleanTarget"},{"children":null,"isAvailable":true,"target":"audio/SoundSettings/cinemaStudio","title":"Cinema Studio 9.1ch","type":"booleanTarget"}],"isAvailable":true,"target":"","title":"Sound Setting","type":"directory"},{"children":[{"children":null,"isAvailable":true,"target":"illumination/IlluminationSettings/colorPattern","title":"Color Pattern","type":"enumTarget"},{"children":null,"isAvailable":true,"target":"illumination/IlluminationSettings/dimmer","title":"Dimmer","type":"enumTarget"}],"isAvailable":true,"target":"","title":"Illumination","type":"directory"}]]}

@broglep
Copy link

broglep commented Oct 7, 2020

I did have a chance today to capture what the sony app is doing. regarding songpal it is doing the following for discovery:

  1. guide getServiceProtocols
  2. getVersions for each service
  3. getMethodTypes for each service

Volume and input is controlled via UPnP. Probably they are shifting functionality towards UPnP and remove their custom songpal solution. It appears that they are using AVTransport SetAVTransportURI to switch between the different inputs, but I could not figure out the details.

@rytilahti
Copy link
Owner

1. guide getServiceProtocols

I suppose this is to figure out if the device should be spoken over websocket vs. xhr post.

2. getVersions for each service

For api compatibility, the current python-songpal implementation takes one of the versions (maybe the first one?), but most of it is hardcoded at the moment so...

3. getMethodTypes for each service

This will give the method signatures incl. return values. This is what gets done on all services by python-songpal to populate the internal structures.

Volume and input is controlled via UPnP. Probably they are shifting functionality towards UPnP and remove their custom songpal solution. It appears that they are using AVTransport SetAVTransportURI to switch between the different inputs, but I could not figure out the details.

Hmm. There are some cases in other models that are controlled via the UPnP APIs, but using it for volume controls & changing sources (and sinks) is new. Now I'm wondering if that 2014 in the model is for the build year? Could it be that some previous generations used UPnP and they converted away from it to the new API? Anycase, that's not so good news as it makes supporting this much more complicated as there is not much UPnP related code outside the group handling in this library, and there hasn't really been that much interest in contributing to UPnP implementation (see #23).

@broglep
Copy link

broglep commented Oct 7, 2020

I did dig a bit deeper. Input is indeed controlled via UPnP. There is an Input element in the content directory that list the different input together with special uri

<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/"
           xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
           xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/"
           xmlns:dlna="urn:schemas-dlna-org:metadata-1-0/"
           xmlns:arib="urn:schemas-arib-or-jp:elements-1-0/"
           xmlns:av="urn:schemas-sony-com:av">
    <item id="I_14_02_0_-1_00_06_6_23_0_0" restricted="1" parentID="23">
        <dc:title>HDMI1</dc:title>
        <upnp:class>object.item.audioItem</upnp:class>
        <av:liveType>MUSIC_INPUT</av:liveType>
        <res protocolInfo="sony.com:00000000-0000-1010-8000-cc988be9be4b:audio:localRender">
            local://<redacted>:60151/I_14_02_0_-1_00_06_6_23_0_0
        </res>
    </item>
    <item id="I_14_02_0_-1_00_07_7_23_0_0" restricted="1" parentID="23">
        <dc:title>HDMI2</dc:title>
        <upnp:class>object.item.audioItem</upnp:class>
        <av:liveType>MUSIC_INPUT</av:liveType>
        <res protocolInfo="sony.com:00000000-0000-1010-8000-cc988be9be4b:audio:localRender">
            local://<redacted>:60151/I_14_02_0_-1_00_07_7_23_0_0
        </res>
    </item>
    <item id="I_14_02_0_-1_00_04_4_23_0_0" restricted="1" parentID="23">
        <dc:title>TV</dc:title>
        <upnp:class>object.item.audioItem</upnp:class>
        <av:liveType>MUSIC_INPUT</av:liveType>
        <res protocolInfo="sony.com:00000000-0000-1010-8000-cc988be9be4b:audio:localRender">
            local://<redacted>:60151/I_14_02_0_-1_00_04_4_23_0_0
        </res>
    </item>
    <item id="I_97_02_0_-1_00_14_14_23_0_0" restricted="1" parentID="23">
        <dc:title>Bluetooth AUDIO</dc:title>
        <upnp:class>object.item.audioItem</upnp:class>
        <av:liveType>MUSIC_INPUT</av:liveType>
        <res protocolInfo="sony.com:00000000-0000-1010-8000-cc988be9be4b:audio:localRender">
            local://<redacted>:60151/I_97_02_0_-1_00_14_14_23_0_0
        </res>
    </item>
    <item id="I_14_02_0_-1_00_09_9_23_0_0" restricted="1" parentID="23">
        <dc:title>AUDIO</dc:title>
        <upnp:class>object.item.audioItem</upnp:class>
        <av:liveType>MUSIC_INPUT</av:liveType>
        <res protocolInfo="sony.com:00000000-0000-1010-8000-cc988be9be4b:audio:localRender">
            local://<redacted>:60151/I_14_02_0_-1_00_09_9_23_0_0
        </res>
    </item>
</DIDL-Lite>

That url is then used in the SetAVTransportURI

Hmm. There are some cases in other models that are controlled via the UPnP APIs, but using it for volume controls & changing sources (and sinks) is new. Now I'm wondering if that 2014 in the model is for the build year? Could it be that some previous generations used UPnP and they converted away from it to the new API?

Yeah, sound plausible. The UPnP way feels hackish, I guess more likely to moved to songpal from UPnP instead the other way around

Is adding UPnP support even in the scope of this project? I can invest some time to get the input selection to work, but feels like adding it here is the wrong place

@broglep
Copy link

broglep commented Oct 8, 2020

I did wonder if I’m having an old firmware version, but the device is using version M21.R.0182 which seems to be newest version, it is from 03-19-2019

@broglep
Copy link

broglep commented Oct 8, 2020

I have working UPnP code that can control the volume and input (using the async_upnp_client). Now my question is how best to integrate that. My end goal is to have home assistant media player that can control the device.

I see two options:

  1. Extend python-songpal to support devices without getSupportedApiInfo and in those cases try to provide some of the python-songpal functionality via UPnP. Will probably need some refactoring of the code base to support two different modes of discovering songpal methods. For those devices without getSupportedApiInfo would use exsting UPnP X_ScalarWebAPI_ServiceType to discover the different songpal services. And then implementing some of the python-songpal commands to either use songpal method, or if not present, try to use UPnP method.

  2. Create a sony specific dlna_dmr media player that supports input selection

Approach 1) makes this project a bit more complex and would rather turn it into a sony audio devices controlling project. When controlling a BDV-N9200W via home assistant you would essentially not using any of songpal api and do everything via UPnP.

@rytilahti Would be interested in your opinion on what the scope of this project should be and what options you see & prefer

@rytilahti
Copy link
Owner

  1. Extend python-songpal to support devices without getSupportedApiInfo and in those cases try to provide some of the python-songpal functionality via UPnP. Will probably need some refactoring of the code base to support two different modes of discovering songpal methods. For those devices without getSupportedApiInfo would use exsting UPnP

I think the question is can we detect when the UPnP should be used for controlling? Could you post the response for the getServiceProtocols query, maybe it reveals something? Or maybe there is something extra inside the SCD (songpal -dd discover) and check out the proprietary X_<something> elements. Here's what I have on HT-XT3:

    <ns2:X_StandardDMR>1.1</ns2:X_StandardDMR>
    <ns3:magicPacketWakeSupported>1</ns3:magicPacketWakeSupported>
    <ns4:X_compatibleId>MS_DigitalMediaDeviceClass_DMR_V001</ns4:X_compatibleId>
    <ns4:X_deviceCategory>MediaDevices</ns4:X_deviceCategory>
    <ns4:X_hardwareId>VEN_0106&amp;DEV_0400&amp;REV_01</ns4:X_hardwareId>
    <ns5:X_deviceCategory>Multimedia.DMR</ns5:X_deviceCategory>
    <ns2:X_ScalarWebAPI_DeviceInfo>
      <ns2:X_ScalarWebAPI_Version>1.0</ns2:X_ScalarWebAPI_Version>
      <ns2:X_ScalarWebAPI_BaseURL>http://192.168.250.241:10000/sony</ns2:X_ScalarWebAPI_BaseURL>
      <ns2:X_ScalarWebAPI_ServiceList>
        <ns2:X_ScalarWebAPI_ServiceType>guide</ns2:X_ScalarWebAPI_ServiceType>
        <ns2:X_ScalarWebAPI_ServiceType>system</ns2:X_ScalarWebAPI_ServiceType>
        <ns2:X_ScalarWebAPI_ServiceType>audio</ns2:X_ScalarWebAPI_ServiceType>
        <ns2:X_ScalarWebAPI_ServiceType>avContent</ns2:X_ScalarWebAPI_ServiceType>
      </ns2:X_ScalarWebAPI_ServiceList>
    </ns2:X_ScalarWebAPI_DeviceInfo>
    <ns2:X_CIS_DeviceInfo>
      <ns2:X_CIS_Version>1,2</ns2:X_CIS_Version>
      <ns2:X_CIS_v1Info>
        <ns2:X_CIS_Port>33335</ns2:X_CIS_Port>
      </ns2:X_CIS_v1Info>
      <ns2:X_CIS_v2Info>
        <ns2:X_CIS_Port>33336</ns2:X_CIS_Port>
      </ns2:X_CIS_v2Info>
    </ns2:X_CIS_DeviceInfo>

Considering that there is some support for the songpal api (e.g., sound settings & others you tested earlier), we want to have some support in this library for devices without the getSupportedApiInfo anyway.

Wrt. refactoring, I have a local WIP branch to refactor the code base to be more service (audio, avContent, system, ..) centric to make the library easier to extend, to provide a nicer API and to make the code base testable. Alas, at the moment I don't really have time to work on that..

Approach 1) makes this project a bit more complex and would rather turn it into a sony audio devices controlling project. When controlling a BDV-N9200W via home assistant you would essentially not using any of songpal api and do everything via UPnP.

The aim of this project is to allow controlling all devices implementing the "ScalarWebAPI", that's why there is also an open issue for supporting televisions, so having this integrated wouldn't be an issue from my point of view :-) However, if your goal is to just have homeassistant support for your device, perhaps async_upnp_client would accept the UPnP "profile" for these devices, which would make it usable directly with the dlna_dmr integration?

@broglep
Copy link

broglep commented Oct 8, 2020

I could not find anything that would hint at using UPnP directly unfortunately.
I think only the absence of certain service types or methods can be used as signal to decide what to do, e.g the missing avContent

getServiceProtocols:

{"id":1,"results":[["audio",["xhrpost:jsonizer"]],["guide",["xhrpost:jsonizer"]],["illumination",["xhrpost:jsonizer"]],["system",["xhrpost:jsonizer"]]]}

SCD (extract)

 <ns2:X_ScalarWebAPI_DeviceInfo>
      <ns2:X_ScalarWebAPI_Version>1.0</ns2:X_ScalarWebAPI_Version>
      <ns2:X_ScalarWebAPI_BaseURL>http://redacted:10000/sony</ns2:X_ScalarWebAPI_BaseURL>
      <ns2:X_ScalarWebAPI_ServiceList>
        <ns2:X_ScalarWebAPI_ServiceType>guide</ns2:X_ScalarWebAPI_ServiceType>
        <ns2:X_ScalarWebAPI_ServiceType>system</ns2:X_ScalarWebAPI_ServiceType>
        <ns2:X_ScalarWebAPI_ServiceType>illumination</ns2:X_ScalarWebAPI_ServiceType>
        <ns2:X_ScalarWebAPI_ServiceType>audio</ns2:X_ScalarWebAPI_ServiceType>
      </ns2:X_ScalarWebAPI_ServiceList>
    </ns2:X_ScalarWebAPI_DeviceInfo>

(full content can be found here: https://pastebin.com/h42vzREg)

maybe a potential candidate is server headers (the 2.0 part maybe?):

Server: Linux/2.6 UPnP/1.0 Sony-BDV/2.0
X-AV-Server-Info.sony.com: av=5.0; hn=""; cn="Sony Corporation"; mn="BDV-N9200W"; mv="2.0";

Regarding dlna_dmr, yes, the integration works out of the box for most parts, but not the input selection, which is what I need :-)

Now that the scope is clear, I can try to add support for UPnP is in this project. If you feel it would be good to base my work on your WIP refactor code base, feel free to share your code regardless of the WIP status

@rytilahti
Copy link
Owner

rytilahti commented Oct 8, 2020

The description file looks odd, as it doesn't even contain AVTransport (which you mentioned is used for the input selection), nor the RenderingControl which is the DLNA interface for volume controls...

Here's the server header from my device:

Server: Linux/3.10 UPnP/1.0 Sony-HTS/2.0
X-AV-Server-Info.sony.com: av=5.0; cn="Sony Corporation"; mn="HT-XT3"; mv="2.0";

so looks like that's not an usable choice.

I think this leaves the lack of avContent (or rather, the lack of getVolumeInformation under audio) for a potential candidate for detection.

Now that the scope is clear, I can try to add support for UPnP is in this project. If you feel it would be good to base my work on your WIP refactor code base, feel free to share your code regardless of the WIP status

I just created a PR, just in case you want to see what I had planned: #83 . It's based on awfully out-of-date master at the moment, but if you think you'd prefer to base your UPnP enhancements on top of it, I can try to do rebasing at some point. Either way, I think the UPnP controls will live in a separate implementation file (much like the group controls), so it doesn't really matter on which you would base the changes.

Btw, could you check out what methods your illumination service implements? There is no implementation for any of it, so the question is if there is something that could be interesting to have around.

@broglep
Copy link

broglep commented Oct 8, 2020

The description file looks odd, as it doesn't even contain AVTransport (which you mentioned is used for the input selection), nor the RenderingControl which is the DLNA interface for volume controls...

AVTransport and RenderingControl is part of the ip::52323/dmr.xml file, the ip:64321/bdv-nv-ms.xml file is the one that has the ScalarWebAPI. So they basically DNLA Media Renderer and DNLA Media Server is split

Btw: did find https://forum.developer.sony.com/topic/131/bdv-n9200w-no-volume, that hints at your theory @rytilahti that the device is using very early songpal api implementation

Btw, could you check out what methods your illumination service implements? There is no implementation for any of it, so the question is if there is something that could be interesting to have around.
Service illumination

  • getIlluminationSettings
  • getMethodTypes
  • getVersions
  • setIlluminationSettings

@rytilahti
Copy link
Owner

AVTransport and RenderingControl is part of the ip::52323/dmr.xml file, the ip:64321/bdv-nv-ms.xml file is the one that has the ScalarWebAPI. So they basically DNLA Media Renderer and DNLA Media Server is split

Ah, that makes sense, forgot about that...

Btw: did find https://forum.developer.sony.com/topic/131/bdv-n9200w-no-volume, that hints at your theory @rytilahti that the device is using very early songpal api implementation

Ah, that explains a bit. So, the UPnP access could then be used as a fallback for those older devices (and there may also be some cases where UPnP could be useful for newer implementations, too: #5 and #23).

re: illumination, what settings are being offered if you call getIlluminationSettings?

@pablofiscella
Copy link

Hi all. Could you tell me if this is a compatibility problem? Home assistant discovers the computer but the media player object does not appear.

If I use it from the command line I have this error.
Thanks

C:\Users\Milena>songpal -dd --endpoint http://192.168.0.49:10000/sony dump-devinfo
Setting debug level to 2
DEBUG:root:Using endpoint http://192.168.0.49:10000/sony
DEBUG:songpal.device:Endpoint: http://192.168.0.49:10000/sony
DEBUG:songpal.device:Guide endpoint: http://192.168.0.49:10000/sony/guide
DEBUG:songpal.device:> POST http://192.168.0.49:10000/sony/guide with body: {'method': 'getSupportedApiInfo', 'params': [{}], 'id': 1, 'version': '1.0'}
DEBUG:songpal.device:Received 200: <bound method ClientResponse.text of <ClientResponse(http://192.168.0.49:10000/sony/guide) [200 OK]>
<CIMultiDictProxy('Connection': 'close', 'Content-Length': '43', 'Content-Type': 'application/json')>

Unable to get supported methods: Got an error for getSupportedApiInfo: NoSuchMethod (12): getSupportedApiInfo

@toams
Copy link

toams commented Jul 29, 2021

It looks like you have a older device which currently isn't supported by python-songpal.

getSupportedApiInfo: NoSuchMethod (12): getSupportedApiInfo

afaik this means python-songpal cant receive all the needed information from your device the regular way. there might be other ways (see above posts) but those aren't implemented yet

@manuel82-241
Copy link

Hi, I have a sony BDV-N9200W home theater. It turns on but no setup menu appears on the screen and I can't open the blue ray disc cover either. It won't let me change the function with the remote or anything, I've tried pressing play and eject for a few seconds and it doesn't do anything except a small clack but I still can't access to update firmware or anything. Can anybody help me?
Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants