Google music in HA

I have made a component that lets you stream music from Google music to your media player.

The component is here: https://github.com/Danielhiversen/home-assistant_config/blob/master/custom_components/switch/gmusic.py

The config to set it up is here: https://github.com/Danielhiversen/home-assistant_config/blob/master/packages/gmusic.yaml
You need both the input_select and switch part in the config.

It requires that you run 0.38.0.dev0 or newer.
You also have to install this library first: http://unofficial-google-music-api.readthedocs.io/en/latest/usage.html#usage
Run pip install gmusicapi to install it.

Edit: Might only work with chromecast.

28 Likes

Wow, this is exactly what ive been looking for. Thanks Daniel, great work as always!

Anyone got this up and running?

I get an error saying it cannot setup switch.gmusic

Have you installed gmusicapi? Run pip install gmusicapi to install it.
Do you see any “Failed to log in” error?

Start ipython and try this code:

from gmusicapi import Mobileclient
api = Mobileclient()
api.login(config['user'],config['password'], config['device_id'])

Where you replace the config info with the info you added in your config file.

Hi
Yes it is installed.

Running ipython gives me:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-c82575be6bab> in <module>()
      1 from gmusicapi import Mobileclient
      2 api = Mobileclient()
----> 3 api.login(config['REMOVED'],config['REMOVED'], config['REMOVED'])

NameError: name 'config' is not defined

Replace config[‘user’] with our google email (the same as you have in the config)
config[‘password’] with your password.

api.login(user, password, device_id)

The parameters are described here:
http://unofficial-google-music-api.readthedocs.io/en/latest/reference/mobileclient.html#gmusicapi.clients.Mobileclient.login

Ah, sorry. Never used ipython before.

That gives me:

Out[3]: True

1 Like

I will add more debug info tomorrow.

Have added some debug info now.

Great, thanks
Unfortunately I cannot test this until I can upgrade to 38-DEV without issues.
I´m stuck on 37.1 for now.

Back on 38-DEV and updated to latest compnents.

Now I have:

17-02-10 14:18:46 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/asyncio/tasks.py", line 232, in _step
    result = coro.throw(exc)
  File "/usr/local/lib/python3.4/site-packages/homeassistant/core.py", line 1018, in _event_to_service_call
    yield from service_handler.func(service_call)
  File "/usr/local/lib/python3.4/site-packages/homeassistant/components/switch/__init__.py", line 107, in async_handle_switch_service
    yield from switch.async_turn_on()
  File "/usr/local/lib/python3.4/asyncio/futures.py", line 388, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/local/lib/python3.4/asyncio/tasks.py", line 285, in _wakeup
    value = future.result()
  File "/usr/local/lib/python3.4/asyncio/futures.py", line 277, in result
    raise self._exception
  File "/usr/local/lib/python3.4/concurrent/futures/thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/pi/.homeassistant/custom_components/switch/gmusic.py", line 120, in turn_on
    self._play()
  File "/home/pi/.homeassistant/custom_components/switch/gmusic.py", line 192, in _play
    option = self.hass.states.get(self._playlist).state
AttributeError: 'NoneType' object has no attribute 'state

Just added some more debug info.

But it seams that you have not defined the correct input_select component:

This line https://github.com/Danielhiversen/home-assistant_config/blob/master/packages/gmusic.yaml#L21
indicates that you need to have an input_select called music, and that is defined here: https://github.com/Danielhiversen/home-assistant_config/blob/master/packages/gmusic.yaml#L2

I have this

input_select:
  music:
    name: Music
    options:
     - " "   # Should be empty
    icon: mdi:music-note
  media_player:
    name: Media player
    options: # entity_ids of your media players
     - "kitchen"
     - "livingroom"
     - "ute"
    icon: mdi:music-note

What I changed was the name Music from Musikk

Hmm, and do you have

   playlist: music # entity id of the input select used for playlist

as part of - platform: gmusic ?
https://github.com/Danielhiversen/home-assistant_config/blob/master/packages/gmusic.yaml#L21

Ok, now it loads the playlists and I can start the music on a player.
But it plays like 1 second on each track then skips.

I´m using Squeezeboxes players

Ok, that is a bug in my code.
I have not found a good method to now when the song is finished, and then start the next song.
So the method I am using with Chromecast, is probably not good enough. I will look in to it.

Hmm
It´s strange, when I click the switch to turn off it continue to play without skips.
How is it handling changing player while switch is on? Maybe it skipped because of sending url to several players?

Also, when turning mediaplayer off it automatically starts again if google switch is on

@Danielhiversen

First, let me say that the installation was not straightforward for me, not being involved in linux much myself. I am running 0.38.2 on a Raspberry Pi. I found that on Hassbian (the official homeassistant image for Raspberry Pi), Home Assistant is installed in a virtual environment that cannot access gmusicapi unless it is installed inside the virtualenv. For me the installation was a multi-step process.

sudo apt-get update
sudo apt-get install python-pip
sudo su -s /bin/bash homeassistant
source /srv/homeassistant/bin/activate
pip install gmusicapi

After all that jazz, I still have errors in my log. I have verified that I have a correct android_id (by copying from My TUNE Device on android). I also verified all the yaml declarations (had to fix some indentation errors), and that gmusic.py is executable. I really don’t know what the problem is. If it makes any difference, the media player is a chromecast.

17-02-13 19:38:39 ERROR (Thread-11) [custom_components.switch.gmusic] Failed to get track (GetStreamUrl: 403 Client Error: Forbidden for url: https://mclients.googleapis.com/music/mplay?tier=fr&opt=hi&pt=e&hl=en_US&net=mob&dv=0&slt=1487014719641&sig=Pj_p-KhNYtjr96IRfiyBRvSYz9I&songid=892d4d8b-d47a-357b-9196-1d240f30a152
(requests kwargs: {'allow_redirects': False, 'url': 'https://mclients.googleapis.com/music/mplay', 'method': 'GET', 'headers': {'X-Device-ID': '10247041828371776762', 'Authorization': '<omitted>'}, 'params': {'tier': 'fr', 'opt': 'hi', 'pt': 'e', 'hl': 'en_US', 'net': 'mob', 'dv': 0, 'slt': '1487014719641', 'sig': b'Pj_p-KhNYtjr96IRfiyBRvSYz9I', 'songid': '892d4d8b-d47a-357b-9196-1d240f30a152'}})
(response was: '<HTML>\n<HEAD>\n<TITLE>Forbidden</TITLE>\n</HEAD>\n<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n<H1>Forbidden</H1>\n<H2>Error 403</H2>\n</BODY>\n</HTML>\n'))
17-02-13 19:38:39 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.4/site-packages/gmusicapi/protocol/shared.py", line 218, in perform
    response.raise_for_status()
  File "/srv/homeassistant/lib/python3.4/site-packages/requests/models.py", line 909, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://mclients.googleapis.com/music/mplay?tier=fr&opt=hi&pt=e&hl=en_US&net=mob&dv=0&slt=1487014719641&sig=Pj_p-KhNYtjr96IRfiyBRvSYz9I&songid=892d4d8b-d47a-357b-9196-1d240f30a152

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 171, in _next_track
    url = self._api.get_stream_url(track['trackId'])
  File "<decorator-gen-102>", line 2, in get_stream_url
  File "/srv/homeassistant/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 293, in wrapper
    return function(*args, **kw)
  File "/srv/homeassistant/lib/python3.4/site-packages/gmusicapi/clients/mobileclient.py", line 371, in get_stream_url
    return self._make_call(mobileclient.GetStreamUrl, song_id, device_id, quality)
  File "/srv/homeassistant/lib/python3.4/site-packages/gmusicapi/clients/shared.py", line 84, in _make_call
    return protocol.perform(self.session, self.validate, *args, **kwargs)
  File "/srv/homeassistant/lib/python3.4/site-packages/gmusicapi/protocol/shared.py", line 226, in perform
    raise CallFailure(err_msg, call_name)
gmusicapi.exceptions.CallFailure: GetStreamUrl: 403 Client Error: Forbidden for url: https://mclients.googleapis.com/music/mplay?tier=fr&opt=hi&pt=e&hl=en_US&net=mob&dv=0&slt=1487014719641&sig=Pj_p-KhNYtjr96IRfiyBRvSYz9I&songid=892d4d8b-d47a-357b-9196-1d240f30a152
(requests kwargs: {'allow_redirects': False, 'url': 'https://mclients.googleapis.com/music/mplay', 'method': 'GET', 'headers': {'X-Device-ID': '10247041828371776762', 'Authorization': '<omitted>'}, 'params': {'tier': 'fr', 'opt': 'hi', 'pt': 'e', 'hl': 'en_US', 'net': 'mob', 'dv': 0, 'slt': '1487014719641', 'sig': b'Pj_p-KhNYtjr96IRfiyBRvSYz9I', 'songid': '892d4d8b-d47a-357b-9196-1d240f30a152'}})
(response was: '<HTML>\n<HEAD>\n<TITLE>Forbidden</TITLE>\n</HEAD>\n<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n<H1>Forbidden</H1>\n<H2>Error 403</H2>\n</BODY>\n</HTML>\n')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/tasks.py", line 233, in _step
    result = coro.throw(exc)
  File "/srv/homeassistant/lib/python3.4/site-packages/homeassistant/core.py", line 1018, in _event_to_service_call
    yield from service_handler.func(service_call)
  File "/srv/homeassistant/lib/python3.4/site-packages/homeassistant/components/switch/__init__.py", line 107, in async_handle_switch_service
    yield from switch.async_turn_on()
  File "/usr/lib/python3.4/asyncio/futures.py", line 388, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.4/asyncio/tasks.py", line 286, in _wakeup
    value = future.result()
  File "/usr/lib/python3.4/asyncio/futures.py", line 277, in result
    raise self._exception
  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 120, in turn_on
    self._play()
  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 206, in _play
    self._next_track()
  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 175, in _next_track
    return _next_track()
NameError: name '_next_track' is not defined

Just added this and it worked first time. It seems to keep skipping the track though after about the first 10 seconds, and the only way to stop it doing so is to turn off the slider on the frontend, therefore turning off the music.

Tried to use Kodi for the media player.

17-02-14 23:47:24 INFO (Thread-1) [gmusicapi.protocol.shared] could not locate client caller in stack:
  File "/usr/lib/python3.4/threading.py", line 888, in _bootstrap
    self._bootstrap_inner()

  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()

  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 65, in _worker
    work_item.run()

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 120, in turn_on
    self._play()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 206, in _play
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 187, in _next_track
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 171, in _next_track
    url = self._api.get_stream_url(track['trackId'])

  File "<decorator-gen-102>", line 2, in get_stream_url

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 293, in wrapper
    return function(*args, **kw)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/mobileclient.py", line 371, in get_stream_url
    return self._make_call(mobileclient.GetStreamUrl, song_id, device_id, quality)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/shared.py", line 84, in _make_call
    return protocol.perform(self.session, self.validate, *args, **kwargs)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/protocol/shared.py", line 199, in perform
    log.debug("%s(args=%s, kwargs=%s)",

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 107, in __getattr__
    stack = traceback.extract_stack()

17-02-14 23:47:25 INFO (Thread-1) [gmusicapi.protocol.shared] could not locate client caller in stack:
  File "/usr/lib/python3.4/threading.py", line 888, in _bootstrap
    self._bootstrap_inner()

  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()

  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 65, in _worker
    work_item.run()

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 120, in turn_on
    self._play()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 206, in _play
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 187, in _next_track
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 171, in _next_track
    url = self._api.get_stream_url(track['trackId'])

  File "<decorator-gen-102>", line 2, in get_stream_url

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 293, in wrapper
    return function(*args, **kw)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/mobileclient.py", line 371, in get_stream_url
    return self._make_call(mobileclient.GetStreamUrl, song_id, device_id, quality)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/shared.py", line 84, in _make_call
    return protocol.perform(self.session, self.validate, *args, **kwargs)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/protocol/shared.py", line 243, in perform
    log.debug(cls.filter_response(parsed_response))

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 107, in __getattr__
    stack = traceback.extract_stack()

17-02-14 23:47:25 INFO (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: service=play_media, service_call_id=3052433168-19, service_dataskyjam&begin=0&upn=RRje980bWwE&o=00658768575318539133&ratebypass=yes&ip=<IP-REMOVED>&ipbits=0&expire=1487116134&sparams=expire,id,ip,ipbits,itag,mm,mn,ms,mv,87115983&mv=m&pl=24, entity_id=media_player.kodi_laptop, domain=media_player>
17-02-14 23:47:27 INFO (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: new_state=<state media_player.kodi_laptop=playing; friendly_na17-02-14T23:47:23.835552+00:00>, old_state=<state media_player.kodi_laptop=playing; friendly_name=Kodi Laptop, media_content_type=audio, media_duration=215,
17-02-14 23:47:27 INFO (MainThread) [homeassistant.core] Bus:Handling <Event service_executed[L]: service_call_id=3052433168-19>
17-02-14 23:47:28 INFO (Thread-1) [gmusicapi.protocol.shared] could not locate client caller in stack:
  File "/usr/lib/python3.4/threading.py", line 888, in _bootstrap
    self._bootstrap_inner()

  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()

  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 65, in _worker
    work_item.run()

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 120, in turn_on
    self._play()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 206, in _play
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 187, in _next_track
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 187, in _next_track
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 171, in _next_track
    url = self._api.get_stream_url(track['trackId'])

  File "<decorator-gen-102>", line 2, in get_stream_url

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 293, in wrapper
    return function(*args, **kw)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/mobileclient.py", line 371, in get_stream_url
    return self._make_call(mobileclient.GetStreamUrl, song_id, device_id, quality)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/shared.py", line 84, in _make_call
    return protocol.perform(self.session, self.validate, *args, **kwargs)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/protocol/shared.py", line 199, in perform
    log.debug("%s(args=%s, kwargs=%s)",

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 107, in __getattr__
    stack = traceback.extract_stack()

17-02-14 23:47:28 INFO (Thread-1) [gmusicapi.protocol.shared] could not locate client caller in stack:
  File "/usr/lib/python3.4/threading.py", line 888, in _bootstrap
    self._bootstrap_inner()

  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()

  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 65, in _worker
    work_item.run()

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 120, in turn_on
    self._play()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 206, in _play
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 187, in _next_track
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 187, in _next_track
    self._next_track()

  File "/home/homeassistant/.homeassistant/custom_components/switch/gmusic.py", line 171, in _next_track
    url = self._api.get_stream_url(track['trackId'])

  File "<decorator-gen-102>", line 2, in get_stream_url

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 293, in wrapper
    return function(*args, **kw)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/mobileclient.py", line 371, in get_stream_url
    return self._make_call(mobileclient.GetStreamUrl, song_id, device_id, quality)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/clients/shared.py", line 84, in _make_call
    return protocol.perform(self.session, self.validate, *args, **kwargs)

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/protocol/shared.py", line 243, in perform
    log.debug(cls.filter_response(parsed_response))

  File "/srv/homeassistant/homeassistant_venv/lib/python3.4/site-packages/gmusicapi/utils/utils.py", line 107, in __getattr__
    stack = traceback.extract_stack()

17-02-14 23:47:28 INFO (MainThread) [homeassistant.core] Bus:Handling <Event call_service[L]: service=play_media, service_call_id=3052433168-20, service_data&source=skyjam&begin=0&upn=7EjTEuB5U2c&o=00658768575318539133&ratebypass=yes&ip=<IP-REMOVED>&ipbits=0&expire=1487116138&sparams=expire,id,ip,ipbits,itag,mm,mcims&ms=au&mt=1487115983&mv=m&pl=24, entity_id=media_player.kodi_laptop, domain=media_player>
17-02-14 23:47:31 INFO (MainThread) [homeassistant.core] Bus:Handling <Event state_changed[L]: new_state=<state media_player.kodi_laptop=playing; friendly_na17-02-14T23:47:23.835552+00:00>, old_state=<state media_player.kodi_laptop=playing; friendly_name=Kodi Laptop, media_content_type=audio, media_duration=326, aptop>
17-02-14 23:47:31 INFO (MainThread) [homeassistant.core] Bus:Handling <Event service_executed[L]: service_call_id=3052433168-20>
17-02-14 23:47:32 INFO (Thread-1) [gmusicapi.protocol.shared] could not locate client caller in stack:
  File "/usr/lib/python3.4/threading.py", line 888, in _bootstrap
    self._bootstrap_inner()

  File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner
    self.run()

  File "/usr/lib/python3.4/threading.py", line 868, in run
    self._target(*self._args, **self._kwargs)

  File "/usr/lib/python3.4/concurrent/futures/thread.py", line 65, i

@DavidSpivey Did you manage to make it work on HASSBIAN?
Thanks.