B5r1oJ0A9G / teufel_raumfeld

Integration for Teufel smart speaker (aka Raumfeld Multiroom) into https://www.home-assistant.io/.
GNU General Public License v3.0
31 stars 7 forks source link

Feature Request: Spotify in SingleRoom mode #4

Open TimNN opened 3 years ago

TimNN commented 3 years ago

Hi!

First of all, thank you for this! I've been experimenting a bit with this and found that Spotify does not appear to be supported in SingleRoom mode.

To recap: Raumfeld supports two modes for Spotify: SingleRoom and MultiRoom. In SingleRoom mode, each room is separately available as a Device in Spotify. In MultiRoom mode, a single Device is available in Spotify, and the Teufel App can be used to configure which speakers actually play the music from Spotify.

Using Spotify in MultiRoom mode seems to mostly work (though I haven't experimented long with it).

Spotify in SingleRoom mode does not work: The Room shows as not active / playing. I suspect that this is because of this:

$ curl -L speaker-wohnzimmer:47365/getZones
<?xml version='1.0' encoding='UTF-8'?>
<zoneConfig numRooms='2' spotifyMode='singleRoom'>
 <zones>
  <zone udn='uuid:36C2A43C-B31C-4572-9EC1-0F43CFA40BB5'>
   <room name='Schlafzimmer' udn='uuid:b8f30d11-9a37-40c0-a9d5-fb334955de66' powerState='ACTIVE'>
    <renderer udn='uuid:1225735b-aec8-4058-892e-01018aa7d420' name='Speaker Schlafzimmer'></renderer>
   </room>
  </zone>
 </zones>
 <unassignedRooms>
  <room name='Wohnzimmer' udn='uuid:9b46f7f7-94e7-45f4-9e4f-49a45a7d2fbb' powerState='ACTIVE'>
   <renderer udn='uuid:666d35e9-f74f-4c0d-a59e-270f39e20a15' name='Speaker Wohnzimmer' spotifyConnect='active'></renderer>
  </room>
 </unassignedRooms>
</zoneConfig>

Note that the room where Spotify is active is listed as in unassignedRooms.

I don't understand enough about the data model here to determine if there's an ~easy fix for this or not. I'd be happy to test potential patches or even to try and write a patch myself if you can point me in the correct direction.

(Note: I totally understand if this is not a priority for you, but wanted to open this so that there's at least a central place for tracking this).

TimNN commented 3 years ago

(Btw, I suspect that it would be possibly to control Spotify playing on Raumfeld devices using the Spotify Integegration, however what I'm looking for is basic controls (e.g. play/pause, next, volume) irrespective of what is currently playing, so this wouldn't help me much).

B5r1oJ0A9G commented 3 years ago

I guess you're pointing in the right direction. Spotify in singleRoom mode is likely using the device renderer directly. To prevent conflicts it would also make sense to ensure the respective speakers are not member of a zone - what finally gives unassignedRooms a reason to exist.

When you look at a current response of speaker-wohnzimmer:47365/getZones, do you find the Unique Device Name (UDN) of a room listed in unassingedRooms with spotifyConnect='active' again in the response of speaker-wohnzimmer:47365/listDevices? In the getZones reponse shared above it would have been the UDN uuid:666d35e9-f74f-4c0d-a59e-270f39e20a15.

TimNN commented 3 years ago

The room does not show up, but the renderer does:

$ curl -L speaker-wohnzimmer:47365/listDevices
<?xml version='1.0' encoding='UTF-8'?>
<devices>
 <device udn='uuid:1225735b-aec8-4058-892e-01018aa7d420' type='urn:schemas-upnp-org:device:MediaRenderer:1' location='http://192.168.3.116:54421/1225735b-aec8-4058-892e-01018aa7d420.xml'>Speaker Schlafzimmer</device>
 <device udn='uuid:1f63dfb3-f96c-49b6-85fe-4807a5470fd1' type='urn:schemas-raumfeld-com:device:ConfigDevice:1' location='http://192.168.3.115:60751/1f63dfb3-f96c-49b6-85fe-4807a5470fd1.xml'>Raumfeld ConfigDevice</device>
 <device udn='uuid:666d35e9-f74f-4c0d-a59e-270f39e20a15' type='urn:schemas-upnp-org:device:MediaRenderer:1' location='http://192.168.3.115:49957/666d35e9-f74f-4c0d-a59e-270f39e20a15.xml'>Speaker Wohnzimmer</device>
 <device udn='uuid:6daa3668-9a53-4ea2-bd2e-2dbe0c5ea8c5' type='urn:schemas-raumfeld-com:device:RaumfeldDevice:1' location='http://192.168.3.116:51146/6daa3668-9a53-4ea2-bd2e-2dbe0c5ea8c5.xml'>Teufel Raumfeld Device</device>
 <device udn='uuid:84064897-c811-4c8a-b79d-ff8f5280321b' type='urn:schemas-upnp-org:device:MediaServer:1' location='http://192.168.3.115:59198/84064897-c811-4c8a-b79d-ff8f5280321b.xml'>Raumfeld MediaServer</device>
 <device udn='uuid:9E67F123-86B5-4137-BDE3-569F56E05BF9' type='urn:schemas-upnp-org:device:MediaRenderer:1' location='http://192.168.3.115:59852/9E67F123-86B5-4137-BDE3-569F56E05BF9.xml'>Schlafzimmer</device>
 <device udn='uuid:b3516060-b8b2-49b1-ab64-0903f6261421' type='urn:schemas-raumfeld-com:device:RaumfeldDevice:1' location='http://192.168.3.115:55659/b3516060-b8b2-49b1-ab64-0903f6261421.xml'>Teufel Raumfeld Device</device>
</devices>
B5r1oJ0A9G commented 3 years ago

Would have been too easy, I guess :) Can you test whether you can play/pause with the following code against the renderer location (under same conditions as the previous test)?

from hassfeld.upnp import pause, play

location = "http://192.168.3.115:49957/666d35e9-f74f-4c0d-a59e-270f39e20a15.xml"
play(location)
#pause(location)
TimNN commented 3 years ago

play and pause work. So do {set,get}_volume, {next,previous}_track and get_position_info.

upnp.get_media_info(location) does not work: Unexpected error with get_media_info: <class 'AttributeError'>No attribute or action found with name 'GetMediaInfo'.

I haven't tested any of the other methods.

B5r1oJ0A9G commented 3 years ago

Great! With this we can work.

B5r1oJ0A9G commented 3 years ago

Can you please provide me the content of the sites /rendercontrol.xml and /avtransport.xml from the location of a renderer device having spotifyConnect='ACTIVE'? I'd like to see whether there is any difference to a regular/room render device.

TimNN commented 3 years ago
$ curl -sL http://192.168.3.115:55517/rendercontrol.xml (click to expand) ```xml 1 0 PlaySystemSound InstanceID in A_ARG_TYPE_InstanceID Sound in A_ARG_TYPE_SystemSound GetMute InstanceID in A_ARG_TYPE_InstanceID Channel in A_ARG_TYPE_Channel CurrentMute out Mute SetMute InstanceID in A_ARG_TYPE_InstanceID Channel in A_ARG_TYPE_Channel DesiredMute in Mute GetVolume InstanceID in A_ARG_TYPE_InstanceID Channel in A_ARG_TYPE_Channel CurrentVolume out Volume SetVolume InstanceID in A_ARG_TYPE_InstanceID Channel in A_ARG_TYPE_Channel DesiredVolume in Volume ChangeVolume InstanceID in A_ARG_TYPE_InstanceID Amount in A_ARG_TYPE_VolumeDifference GetVolumeDB InstanceID in A_ARG_TYPE_InstanceID Channel in A_ARG_TYPE_Channel CurrentVolume out VolumeDB SetVolumeDB InstanceID in A_ARG_TYPE_InstanceID Channel in A_ARG_TYPE_Channel DesiredVolume in VolumeDB GetBalance InstanceID in A_ARG_TYPE_InstanceID CurrentBalance out Balance SetBalance InstanceID in A_ARG_TYPE_InstanceID DesiredBalance in Balance GetLineInStreamURL URL out A_ARG_TYPE_String Mimetype out A_ARG_TYPE_String SetFilter InstanceID in A_ARG_TYPE_InstanceID LowDB in A_ARG_TYPE_Filter MidDB in A_ARG_TYPE_Filter HighDB in A_ARG_TYPE_Filter GetFilter InstanceID in A_ARG_TYPE_InstanceID LowDB out A_ARG_TYPE_Filter MidDB out A_ARG_TYPE_Filter HighDB out A_ARG_TYPE_Filter ToggleFilter InstanceID in A_ARG_TYPE_InstanceID FilterName in A_ARG_TYPE_FilterName Enable in A_ARG_TYPE_Boolean QueryFilter InstanceID in A_ARG_TYPE_InstanceID FilterName in A_ARG_TYPE_FilterName Enabled out A_ARG_TYPE_Boolean SetDeviceSetting InstanceID in A_ARG_TYPE_InstanceID Name in A_ARG_TYPE_SettingName Value in A_ARG_TYPE_SettingValue GetDeviceSetting InstanceID in A_ARG_TYPE_InstanceID Name in A_ARG_TYPE_SettingName Value out A_ARG_TYPE_SettingValue LastChange string Mute boolean Volume ui2 0 100 1 VolumeDB i2 Balance i2 -3072 3072 128 A_ARG_TYPE_Channel string Master Input A_ARG_TYPE_SystemSound string Success Failure A_ARG_TYPE_InstanceID ui4 A_ARG_TYPE_String string A_ARG_TYPE_Filter i4 -1536 1536 A_ARG_TYPE_FilterName string stereo-widening A_ARG_TYPE_SettingName string A_ARG_TYPE_SettingValue string A_ARG_TYPE_VolumeDifference i1 -100 100 1 A_ARG_TYPE_Boolean boolean ```
$ curl -sL http://192.168.3.115:55517/avtransport.xml (click to expand) ```xml 1 0 SetAVTransportURI InstanceID in A_ARG_TYPE_InstanceID CurrentURI in AVTransportURI CurrentURIMetaData in AVTransportURIMetaData SetNextAVTransportURI InstanceID in A_ARG_TYPE_InstanceID NextURI in AVTransportURI NextURIMetaData in AVTransportURIMetaData SetNextStartTriggerTime InstanceID in A_ARG_TYPE_InstanceID TimeService in A_ARG_TYPE_WallClockService StartTime in A_ARG_TYPE_WallClockTime GetPositionInfo InstanceID in A_ARG_TYPE_InstanceID TrackDuration out CurrentTrackDuration RelTime out RelativeTimePosition GetTransportInfo InstanceID in A_ARG_TYPE_InstanceID CurrentTransportState out TransportState CurrentTransportStatus out TransportStatus CurrentSpeed out TransportPlaySpeed GetTransportSettings InstanceID in A_ARG_TYPE_InstanceID PlayMode out CurrentPlayMode Stop InstanceID in A_ARG_TYPE_InstanceID Rewind InstanceID in A_ARG_TYPE_InstanceID Position out RelativeTimePosition FastForward InstanceID in A_ARG_TYPE_InstanceID Position out RelativeTimePosition Pause InstanceID in A_ARG_TYPE_InstanceID Play InstanceID in A_ARG_TYPE_InstanceID Speed in TransportPlaySpeed Next InstanceID in A_ARG_TYPE_InstanceID Previous InstanceID in A_ARG_TYPE_InstanceID Seek InstanceID in A_ARG_TYPE_InstanceID Unit in A_ARG_TYPE_SeekMode Target in A_ARG_TYPE_SeekTarget SetPlayMode InstanceID in A_ARG_TYPE_InstanceID NewPlayMode in CurrentPlayMode EnterManualStandby InstanceID in A_ARG_TYPE_InstanceID EnterAutomaticStandby InstanceID in A_ARG_TYPE_InstanceID LeaveStandby InstanceID in A_ARG_TYPE_InstanceID GetSpotifyPreset InstanceID in A_ARG_TYPE_InstanceID Button in A_ARG_TYPE_ButtonNumber Preset out AVTransportURI Metadata out A_ARG_TYPE_JsonObject TransportState string STOPPED PLAYING TRANSITIONING NO_MEDIA_PRESENT TransportStatus string AVTransportURI string AVTransportURIMetaData string CurrentPlayMode string NORMAL SHUFFLE REPEAT_ALL REPEAT_ONE RANDOM NORMAL CurrentTrackDuration string PowerState string RelativeTimePosition string BufferFilled ui4 OwnsAudioResource boolean LastChange string A_ARG_TYPE_InstanceID ui4 A_ARG_TYPE_SeekMode string ABS_TIME A_ARG_TYPE_SeekTarget string TransportPlaySpeed string 1 A_ARG_TYPE_WallClockTime string A_ARG_TYPE_WallClockService string A_ARG_TYPE_Boolean boolean A_ARG_TYPE_ButtonNumber ui4 A_ARG_TYPE_JsonObject string ```
B5r1oJ0A9G commented 3 years ago

Thanks for sharing! I just applied for the Spotify Premium plan for better testing. Unfortunately only to find out that it doesn't work over different networks. You already spotted the branch where i dumped my first tests. Perhaps you can test it on your side. In case it is already working, the rest should be just a finger exercise :)

TimNN commented 3 years ago

Spotify was simply not on my list (of interest) :)

Then even more so, thanks for looking into this.

Perhaps you can test it on your side.

Done.

One issue:

if room["renderer"]["@spotifyConnect"] == "ACTIVE":

needs to compare against lowercase "active". After fixing that, all the new methods (room_play, room_pause, room_is_spotify_single_room, get_room_transport_info) work from what I can tell.

get_room_transport_info returns {'CurrentTransportState': 'PLAYING', 'CurrentTransportStatus': 'OK', 'CurrentSpeed': '1'} if that is of interest to you.

B5r1oJ0A9G commented 3 years ago

Thanks for the feedback! Did your test cover only hassfeld or teufel_raumfeld as well?

TimNN commented 3 years ago

Ah, I didn't realize that teufel_raumfeld also got updated. Let me try that now.

TimNN commented 3 years ago

Alright, I did some tests:

The room is recognized as "active" when Spotify is playing. However the play state does not appear to be correctly detected: A "Play" (instead of "Pause") button is shown, and attempting to click it fails with Action Play is currently not allowed.

If I manually pause Spotify, and then click the play button, the music starts playing but the action still produces an error:

Error: unhashable type: 'list' (click to expand) ```plain Mar 06 10:50:28 ctrl hass[262080]: 2021-03-06 10:50:28 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [281472900019296] unhashable type: 'list' Mar 06 10:50:28 ctrl hass[262080]: Traceback (most recent call last): Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/components/websocket_api/commands.py", line 136, in handle_call_service Mar 06 10:50:28 ctrl hass[262080]: await hass.services.async_call( Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/core.py", line 1455, in async_call Mar 06 10:50:28 ctrl hass[262080]: task.result() Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/core.py", line 1490, in _execute_service Mar 06 10:50:28 ctrl hass[262080]: await handler.job.target(service_call) Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/helpers/entity_component.py", line 204, in handle_service Mar 06 10:50:28 ctrl hass[262080]: await self.hass.helpers.service.entity_service_call( Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/helpers/service.py", line 595, in entity_service_call Mar 06 10:50:28 ctrl hass[262080]: future.result() # pop exception if have Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/helpers/entity.py", line 664, in async_request_call Mar 06 10:50:28 ctrl hass[262080]: await coro Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/helpers/service.py", line 632, in _handle_entity_call Mar 06 10:50:28 ctrl hass[262080]: await result Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/homeassistant/components/media_player/__init__.py", line 788, in async_media_play_pause Mar 06 10:50:28 ctrl hass[262080]: await self.async_media_play() Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/config/custom_components/teufel_raumfeld/media_player.py", line 349, in async_media_play Mar 06 10:50:28 ctrl hass[262080]: await self.async_update_transport_state() Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/config/custom_components/teufel_raumfeld/media_player.py", line 557, in async_update_transport_state Mar 06 10:50:28 ctrl hass[262080]: info = await self._raumfeld.async_get_room_transport_info(self._rooms) Mar 06 10:50:28 ctrl hass[262080]: File "/home/homeassistant/venv/lib/python3.8/site-packages/hassfeld/__init__.py", line 892, in async_get_room_transport_info Mar 06 10:50:28 ctrl hass[262080]: room_udn = self.resolve["room_to_udn"][room] Mar 06 10:50:28 ctrl hass[262080]: TypeError: unhashable type: 'list' ```
TimNN commented 3 years ago

The error during play can be fixed by passing self._room to async_get_room_transport_info in async_update_transport_state.

Though that does not fix the "play state" detection.

TimNN commented 3 years ago

Logging the result of async_get_room_transport_info:

Mar 06 11:04:10 ctrl hass[262646]: 2021-03-06 11:04:10 DEBUG (MainThread) [custom_components.teufel_raumfeld]
media_player.py->async_update_transport_state:
Transport Info: {'CurrentTransportState': 'PLAYING', 'CurrentTransportStatus': 'OK', 'CurrentSpeed': '1'}
TimNN commented 3 years ago

Alright, I've been experimenting some more:

  1. async_media_pause also uses _rooms as an argument instead of _room in one place.
  2. async_update unconditionally setting the _state seems to part of the issue with the state not being correctly detected.

If I

then the play / pause button in HomeAssistant works.

If HomeAssistant and Spotify disagree on the state, then button in HomeAssistant does not work (because it attempts to do the incorrect action).

B5r1oJ0A9G commented 3 years ago

I merged the changes to master for easier testing (starting from 65947ef). However, I fear I depend on external feedback/support to progress here due to the inability to test on my side.

TimNN commented 3 years ago

Thanks a lot for your work on this!

If just tested this and found the following issue: room_is_spotify_single_room(...) no longer returns the correct result.

With hassfeld master:

>>> import hassfeld
>>> h = hassfeld.RaumfeldHost("speaker-wohnzimmer.lan"); h.start_update_thread()
>>> h.room_is_spotify_single_room('Wohnzimmer')
False

Downgrading back to the dev branch:

>>> import hassfeld
>>> h = hassfeld.RaumfeldHost("speaker-wohnzimmer.lan"); h.start_update_thread()
>>> h.room_is_spotify_single_room('Wohnzimmer')
True

It looks like the "Spotify active" check uses the wrong case again, changing SPOTIFY_ACTIVE = "ACTIVE" to SPOTIFY_ACTIVE = "active" resolves the issue.

Play / Pause from the Home Assistant UI seems to work reliably now! 🎉 🎊 🥳

I'll test this more over the next few days, and will report back with any issues.

B5r1oJ0A9G commented 3 years ago

Thanks for the feedback! The failing "Spotify active" check was indeed a regression. It's fixed again with https://github.com/B5r1oJ0A9G/hassfeld/commit/de86cc9187d3ed46d00519bc8e721f28cdef7b27.

What other controls are missing for single-room support?

Edit: Probably:

{set,get}_volume, {next,previous}_track and get_position_info, resp. get_track_info.

B5r1oJ0A9G commented 3 years ago

In 840a4b1 support for {set,get}_volume, {next,previous}_track is ready for testing.

MaxSchuck commented 2 years ago

I really appreciate the effort that went into this application, and it does work great with local files. But I still experience the exact same issues discussed by Tim, so i wonder, where you solutions commited to the master branch (or whatever I get in HACS with the raumfeld download, or do I have to pick together a working version myself, and if thats the case, how do I do that? I am not savy with this slightly more advanced HA stuff

B5r1oJ0A9G commented 2 years ago

Hello @MaxSchuck ,

@TimNN and me worked on several aspects together. Can you please clarify what exactly you're referring to. Also, some information about your setup can be helpful too. In case it is not about single room mode with Spotify, it would make sense to create a dedicated issue.

MaxSchuck commented 2 years ago

I have trouble using your extension in HA with my Raumfeldspeaker if spotify plays media in Single-Room modus. The speaker is playing via spotify, but in HA it is viewed as off. If i turn it on to change volume for example, spotify gets stopped. Everthing works as expected. If i use the multiroom modus after brief testing. To me, this sounds as if i might just have an outdated version, but i installed via the HACS extension, that should take care of updates for me. Update pollingn is activated

B5r1oJ0A9G commented 2 years ago

@MaxSchuck, There was a regression identified and fiex by c-mellueh (https://github.com/B5r1oJ0A9G/teufel_raumfeld/issues/29#issuecomment-1039052758). Could it be caused by this or do you still face the problem with th current release v0.1.12-alpha

MaxSchuck commented 2 years ago

am on 0.1.12-alpha4 but I still face the same issue sadly.

MaxSchuck commented 2 years ago

allright, now it partly works for me, I don't know what exactly changed, I did a ton of restarting, reinstalling and so on concerning other problems. HA still does not realize if music is playing via spotify multiroom. If I hit play though, it starts playing from the multiroom speaker. Background-image still does not appear, but who cares. What bothers me is that i cant skip or replay songs. Imma just dump the log report here, can't make out what is of relevance and what not

` [140228859544000] 'HassRaumfeldHost' object has no attribute 'async_room_next_track'

Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 193, in handle_call_service await hass.services.async_call( File "/usr/src/homeassistant/homeassistant/core.py", line 1704, in async_call task.result() File "/usr/src/homeassistant/homeassistant/core.py", line 1741, in _execute_service await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)( File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 204, in handle_service await service.entity_service_call( File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 680, in entity_service_call future.result() # pop exception if have File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 964, in async_request_call await coro File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 717, in _handle_entity_call await result File "/config/custom_components/teufel_raumfeld/media_player.py", line 419, in async_media_next_track await self._raumfeld.async_room_next_track(self._room) AttributeError: 'HassRaumfeldHost' object has no attribute 'async_room_next_track' `

ulilicht commented 1 year ago

Hi there, commenting on this old issue again, it seems I experience the same problem.

using v0.1.12-alpha4 installed through HACS 1.30 on Home Assistant version 2023.1.7

I have Teufel Raumfeld devices from the second generation. (Stereo M)

Steps to reproduce:

In addition, I cannot play any media on the device until I use the Raumfeld app to choose anything without Spotify.

What does work:

Happy to help debugging or fixing the issue if you point me in the right direction.

Best Uli

Exception when clicking "next" while Spotify is being played:

Logger: homeassistant.components.websocket_api.http.connection
Source: custom_components/teufel_raumfeld/media_player.py:419 
Integration: Home Assistant WebSocket API (documentation, issues) 
First occurred: 09:15:46 (3 occurrences) 
Last logged: 09:51:39

[547763051328] Error handling message: Unknown error (unknown_error) from fe80::4f9:4b73:e16b:2f7b (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.2 Safari/605.1.15)
[547795794288] 'HassRaumfeldHost' object has no attribute 'async_room_next_track'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 27, in _handle_async_response
    await func(hass, connection, msg)
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 646, in handle_execute_script
    await script_obj.async_run(msg.get("variables"), context=context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1524, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 409, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 453, in _async_step
    self._handle_exception(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 476, in _handle_exception
    raise exception
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 451, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 923, in _async_if_step
    await self._async_run_script(if_data["if_then"])
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1029, in _async_run_script
    await self._async_run_long_action(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 648, in _async_run_long_action
    long_task.result()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1524, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 409, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 453, in _async_step
    self._handle_exception(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 476, in _handle_exception
    raise exception
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 451, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 684, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1755, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1792, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 213, in handle_service
    await service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 678, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 958, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 715, in _handle_entity_call
    await result
  File "/config/custom_components/teufel_raumfeld/media_player.py", line 419, in async_media_next_track
    await self._raumfeld.async_room_next_track(self._room)
AttributeError: 'HassRaumfeldHost' object has no attribute 'async_room_next_track'

Exception when trying to choose media through a Service after Spotify has been used:

Logger: homeassistant.components.websocket_api.http.connection
Source: components/websocket_api/connection.py:150 
Integration: Home Assistant WebSocket API ([documentation](https://www.home-assistant.io/integrations/websocket_api), [issues](https://github.com/home-assistant/home-assistant/issues?q=is%3Aissue+is%3Aopen+label%3A%22integration%3A+websocket_api%22)) 
First occurred: 10:01:54 (1 occurrences) 
Last logged: 10:01:54

[547795794288] Error handling message: Entity media_player.room_wohnzimmer does not support this service. (unknown_error) from fe80::4f9:4b73:e16b:2f7b (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.2 Safari/605.1.15)