Google Fit Support

Let me know if you get to solve your problem, I have the same one, heart rate and sleep show up in Google Fit (Synced through Notify for Mi Band), but my heart_rate and sleep sensors in HA remain empty

Google changed intents for them (sleep and heart rate) :frowning:
Will look at it when weather turns bad again (no outdoor activity).
Best, JR
PS link to Google changes as of May 4th: Sleep and Heart rate API changes

2 Likes

so heart rate and sleep sensors are not working because of API changes from Google’s side, right?

That’s my understanding

Hello everyone.
I already installed GoogleFit in two ways, but I can’t get the heart rate data to appear.
What is currently running is vmanuel / hacs-google-fit.
I am using a Samtband 4.
Does anyone have any idea di that may be happening?

After some research I found that Sleep and HeartRate sensors stopped working due to changes in Google’s API, so either developers didn’t have a time to update or they abandoned the integration.

I’ve found a solution that seems to work (sort off, the refresh_token isn’t really working).

I tried first adding the required scopes to the sensor.py removing my token file but then I got a invalid_scope error, I searched a bit, but couldn’t figure out why.

After some more messing around I found a method that seems to work

Required;

  • Setup the HACS integration a first time so it is authorized (and the token file is generated)
  • This requires some JSON knowledge and now how
  • full “tutorial” must be done in 3599 seconds (so basically within 1 hour, we are going to change the access token, and the get refreshed every hour)

Let’s goo!

  1. Go to oauthplayground

  2. Click on “Step 1 Select & authorize APIs”
    Scroll down to Fitness API v1
    Normally all scopes should be enabled with read and write (this isn’t fully needed, but I didn’t had the time to fully figure out what needs to be enabled)
    If not, these are the ones that worked for me:

  3. Click on “Auhtorize APIs” and go trough the authorization steps

  4. In step 2, click on Exchange authorization code for tokens

  5. On the right you should see something like this:


    copy the full json part on the bottom (with the access_token, scope, …)

  6. open your .<name>_google_fit.token file. This should be on the same level as your configuration.yaml file (I suggest you create a copy and format it, for easy working and having a backup)

  7. Paste the copied json in the token_response part (this should have the same keys, maybe different order)

  8. Copy the full access_token (yellow in reference screenshot), full refresh_token (purple in reference screenshot) to the upper part of the json

  9. Copy the following scopes (green in reference screenshot) to the scopes part (remove the ones you didn’t authorize):

  "scopes": [
    "https://www.googleapis.com/auth/fitness.location.write",
    "https://www.googleapis.com/auth/fitness.sleep.read",
    "https://www.googleapis.com/auth/fitness.heart_rate.read",
    "https://www.googleapis.com/auth/fitness.location.read",
    "https://www.googleapis.com/auth/fitness.activity.read",
    "https://www.googleapis.com/auth/fitness.body.write",
    "https://www.googleapis.com/auth/fitness.activity.write",
    "https://www.googleapis.com/auth/fitness.body.read",
    "https://www.googleapis.com/auth/fitness.sleep.write",
    "https://www.googleapis.com/auth/fitness.heart_rate.write"
  ],
  1. Save it (the token file doesn’t have to be on a single line, formatted also works)
  2. Restart Homeassistant and this should be working :slight_smile:

Refrenced screenshot of my <name>.google_fit.token file (not my full tokens obvisouly) :

I’m still waiting for a new token token to be generated, but this should give any issue (from my knowledge of these tokens, but then again I don’t understand why the scope was giving issues)

1 Like

Success or fail?
Best, JR

I tried this manual solution (Thanks Glenn) and it worked initially but then stopped
I also did some digging into the methods for getting tokens and then coded 2 standalone python routines

The first was using the same method as the various google fit sensors (calling oauth2client.client.Oauth2Webserverflow and then …step1_get_device_and_user code() from the Google api python client) … when this works then it gives you a code to enter at www.google.com/device. With this routine it was quick to try different sets of scopes and see which work/didn’t work and also use the debugger to confirm that it is the google server rejecting the requests

In the second method I used oauth2client.tools.run_flow which then takes you through the browser based authorisation and returns the credentials needed. The routine then writes these into a file whcih can then be renamed to match your expected google fit sensor token file .

Results - as we have all found, any use of the new scopes with the get_device_and_user_code routine fails (and fails after the data has been sent across to https://oauth2.googleapis.com/device/code
Looking at the documentation OAuth 2.0 for TV and Limited-Input Device Applications it does state that this method does support a limited number of scopes (and does not list any fitness scopes) -so perhaps we were lucky that the sensor worked at all

Better news is that the second method (generating the token file) has been running for 48 hours now and is still collecting steps, heart rate and sleep data.

Here is the standalone routine

import os
REQUIREMENTS = [
    'google-api-python-client==1.6.4',
    'oauth2client==4.0.0',
    'httplib2'
]

# Sensor base attributes.

CONF_CLIENT_ID = '32..............apps.googleusercontent.com'
CONF_CLIENT_SECRET = 'H....................5'



TOKEN_FILE = ''

# Endpoint scopes required for the sensor.
# Read more: https://developers.google.com/fit/rest/v1/authorization

SCOPES = ["https://www.googleapis.com/auth/fitness.location.write",
          "https://www.googleapis.com/auth/fitness.sleep.read",
          "https://www.googleapis.com/auth/fitness.heart_rate.read",
          "https://www.googleapis.com/auth/fitness.location.read",
          "https://www.googleapis.com/auth/fitness.activity.read",
          "https://www.googleapis.com/auth/fitness.body.write",
          "https://www.googleapis.com/auth/fitness.activity.write",
          "https://www.googleapis.com/auth/fitness.body.read",
          "https://www.googleapis.com/auth/fitness.sleep.write",
          "https://www.googleapis.com/auth/fitness.heart_rate.write" ]

def do_authentication():

    from oauth2client import client as oauth2client
    from oauth2client import file as oauth2file
    from oauth2client.file import Storage
    from oauth2client.tools import run_flow
    import google.oauth2.credentials

    oauth = oauth2client.OAuth2WebServerFlow(
        client_id=CONF_CLIENT_ID,
        client_secret=CONF_CLIENT_SECRET,
        scope=SCOPES,
        redirect_uri='urn:ietf:wg:oauth:2.0:oob',
    )

    storage = Storage('google_fit.token')
    # Open a web browser to ask the user for credentials.
    credentials = run_flow(oauth, storage)
    assert credentials.access_token is not None
    return credentials.access_token

    token = get_access_token()
    credentials = google.oauth2.credentials.Credentials(token)

    TOKEN_FILE = "google_fit.token"
    storage = oauth2file.Storage(TOKEN_FILE)
    storage.put(credentials)

    return True

do_authentication()
1 Like

Thanks for that :slight_smile:
Now my (digital) heartbeat is visible again and I sleep well (digitally)…
Only hickup was the filename- forgot to rename it to .google_fit.token :frowning:
So far so good- and another mega thanks.
Best, JR

What steps can be taken to update the current integration to work broken sensors again? can someone help

At the moment it does not seem possible to fix this by modifying the sensor.py routine. When HA starts, the sensory.py logic is

  1. Does the token file exist - if yes then use the token file, if no goto step 2
  2. Send the required scopes to google and get a device code for the user to then authenticate (this is shown to the user in the notification message)
  3. Wait for authentication by the user (who needs to open www.google.com/device and enter the device code) and then create the token file

Step 2 is not working because Google is not allowing this method to be used with these new sensitive/restricted fitness scopes, so step 3 never happens and none of the requests for google fit data work.

So in How to resolve the issue with the new API's · Issue #13 · vmanuel/hacs-google-fit · GitHub there is some discussion on how to run the code above in a python environment to create the required token file. (HA needs to restarted after the token file has been created so that it is found in Step 1 above).
Please make sure this new token file is renamed to be exactly what sensor.py is expecting

Generated token lived for 7 days, then got revoked :frowning:
That was with one account, another account token was generated some 18 hours later- let’s see :slight_smile:
Maybe the culprit is testing status, not production? Worth a try?
Best, JR

Yeap! Same here… i have tried something similar a couple of months ago, and have the same problem with token been revoked 7 days before created. Unfortenely I don’t know much of python or auth2, so I was hopping that someone could generated a ‘long-term’ token… I tried the code posted here (thank you so much astronaut63) but today i have to generate a new one too… btw, thank you all, community and developers of home assistant, wonderful piece of project <3… sorry for my english, this is my first post so… :sweat_smile:
Best Regards,
Rodrigo Marinangeli

Yep, 7 days is token lifespan :frowning:
Will try to push to production and see if this helps :slight_smile:
See you all in a week…
Best, JR

I’m also waiting for a few more hours for the 7 days to expire. I have a separate client/token for the Google calendar integration (created using the “old” device method) and then the token file for Google Fit created by the standalone code so it will be interesrting to see if both stop. I had also experienced the 7 day issue on a completely different Windows Google Cal to Outlook synchroisation tool and have now seen the official documentation confirming this limit: Using OAuth 2.0 to Access Google APIs  |  Google Identity

I did spend some time looking at a) using the official google_auth_oauthlib python modules which should allow something closer to the way the Google fit sensor originally worked (a notification message telling you to go to a google address where you approve the scopes and then a verification code to be entered back into Home Assistant - via an Input_text (?) or b) using the oauth callbacks already in HA – but this I think would mean having to open access to HA via DuckDNS and Router port forwards which not everyone wants to do.
I’ve not seen anything that explains what happens if you change your application from testing to production but then do not get it verified . This might be more critical for these fitness scopes
Some of the Google docs talk about “Personal” use applications being exempt from verification but I haven’t found out any more

Maybe I am too impatient as always :slight_smile: but after declaring the Fit app as “production” (no verification was needed) in Google it has been working for 10 days after last token generation via Python script… vs 7 days before :frowning: Fingers crossed!
Reads all our family Google Fit data via MiBand and MiScale2 and displays nicely in HA :slight_smile:
Best, JR

1 Like

I’m getting the following error:

2021-09-30 15:25:16 ERROR (MainThread) [homeassistant.components.sensor] Error adding entities for domain sensor with platform google_fit
Traceback (most recent call last):
  File "C:\Python38\lib\site-packages\homeassistant\helpers\entity_platform.py", line 382, in async_add_entities
    await asyncio.gather(*tasks)
  File "C:\Python38\lib\site-packages\homeassistant\helpers\entity_platform.py", line 587, in _async_add_entity
    await entity.add_to_platform_finish()
  File "C:\Python38\lib\site-packages\homeassistant\helpers\entity.py", line 698, in add_to_platform_finish
    self.async_write_ha_state()
  File "C:\Python38\lib\site-packages\homeassistant\helpers\entity.py", line 464, in async_write_ha_state
    self._async_write_ha_state()
  File "C:\Python38\lib\site-packages\homeassistant\helpers\entity.py", line 505, in _async_write_ha_state
    extra_state_attributes = self.device_state_attributes
  File "C:\Users\stefa\AppData\Roaming\.homeassistant\custom_components\google_fit\sensor.py", line 247, in device_state_attributes
    return self._attributes
AttributeError: 'GoogleFitWeightSensor' object has no attribute '_attributes'

I already tried to remove token files and py cache…

When I restart HA, I also get as soon as I restart the following notification: Authentication code expired, please restart Home-Assistant and try again

1 Like

Same here for me!

Now I am able to get the sensors showing up. Only height and weight data are being provided. All other sensors show this in the Configuration Log: oauth2client.client.HttpAccessTokenRefreshError: unauthorized_client: Unauthorized

Not sure how to resolve this…