From 8cb48615afcf0faed54ca9684ee8167fe3445ce4 Mon Sep 17 00:00:00 2001 From: Robbie Trencheny Date: Sat, 7 May 2016 12:46:45 -0700 Subject: [PATCH] Fitbit Sensor Take Deux (#2002) * Fitbit Sensor * Add configurator image --- .coveragerc | 1 + .../www_static/images/config_fitbit_app.png | Bin 0 -> 46660 bytes homeassistant/components/sensor/fitbit.py | 372 ++++++++++++++++++ requirements_all.txt | 3 + 4 files changed, 376 insertions(+) create mode 100644 homeassistant/components/frontend/www_static/images/config_fitbit_app.png create mode 100644 homeassistant/components/sensor/fitbit.py diff --git a/.coveragerc b/.coveragerc index 2a91d1f17b1..028aacead28 100644 --- a/.coveragerc +++ b/.coveragerc @@ -148,6 +148,7 @@ omit = homeassistant/components/sensor/dht.py homeassistant/components/sensor/efergy.py homeassistant/components/sensor/eliqonline.py + homeassistant/components/sensor/fitbit.py homeassistant/components/sensor/forecast.py homeassistant/components/sensor/glances.py homeassistant/components/sensor/google_travel_time.py diff --git a/homeassistant/components/frontend/www_static/images/config_fitbit_app.png b/homeassistant/components/frontend/www_static/images/config_fitbit_app.png new file mode 100644 index 0000000000000000000000000000000000000000..271a0c6dd47984dfa638572b82cddec82539061c GIT binary patch literal 46660 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 3600: + authd_client.client.refresh_token() + + authd_client.system = authd_client.user_profile_get()["user"]["locale"] + + dev = [] + for resource in config.get("monitored_resources", + FITBIT_DEFAULT_RESOURCE_LIST): + dev.append(FitbitSensor(authd_client, config_path, resource)) + add_devices(dev) + + else: + oauth = fitbit.api.FitbitOauth2Client(config.get("client_id"), + config.get("client_secret")) + + redirect_uri = "{}{}".format(hass.config.api.base_url, + FITBIT_AUTH_CALLBACK_PATH) + + def _start_fitbit_auth(handler, path_match, data): + """Start Fitbit OAuth2 flow.""" + url, _ = oauth.authorize_token_url(redirect_uri=redirect_uri, + scope=["activity", "heartrate", + "nutrition", "profile", + "settings", "sleep", + "weight"]) + handler.send_response(301) + handler.send_header("Location", url) + handler.end_headers() + + def _finish_fitbit_auth(handler, path_match, data): + """Finish Fitbit OAuth2 flow.""" + response_message = """Fitbit has been successfully authorized! + You can close this window now!""" + from oauthlib.oauth2.rfc6749.errors import MismatchingStateError + from oauthlib.oauth2.rfc6749.errors import MissingTokenError + if data.get("code") is not None: + try: + oauth.fetch_access_token(data.get("code"), redirect_uri) + except MissingTokenError as error: + _LOGGER.error("Missing token: %s", error) + response_message = """Something went wrong when + attempting authenticating with Fitbit. The error + encountered was {}. Please try again!""".format(error) + except MismatchingStateError as error: + _LOGGER.error("Mismatched state, CSRF error: %s", error) + response_message = """Something went wrong when + attempting authenticating with Fitbit. The error + encountered was {}. Please try again!""".format(error) + else: + _LOGGER.error("Unknown error when authing") + response_message = """Something went wrong when + attempting authenticating with Fitbit. + An unknown error occurred. Please try again! + """ + + html_response = """Fitbit Auth +

{}

""".format(response_message) + + html_response = html_response.encode("utf-8") + + handler.send_response(HTTP_OK) + handler.write_content(html_response, content_type="text/html") + + config_contents = { + "access_token": oauth.token["access_token"], + "refresh_token": oauth.token["refresh_token"], + "client_id": oauth.client_id, + "client_secret": oauth.client_secret + } + if not config_from_file(config_path, config_contents): + _LOGGER.error("failed to save config file") + + setup_platform(hass, config, add_devices, discovery_info=None) + + hass.http.register_path("GET", FITBIT_AUTH_START, _start_fitbit_auth) + hass.http.register_path("GET", FITBIT_AUTH_CALLBACK_PATH, + _finish_fitbit_auth) + + request_oauth_completion(hass) + + +# pylint: disable=too-few-public-methods +class FitbitSensor(Entity): + """Implementation of a Fitbit sensor.""" + + def __init__(self, client, config_path, resource_type): + """Initialize the Uber sensor.""" + self.client = client + self.config_path = config_path + self.resource_type = resource_type + pretty_resource = self.resource_type.replace("activities/", "") + pretty_resource = pretty_resource.replace("/", " ") + pretty_resource = pretty_resource.title() + if pretty_resource == "Body Bmi": + pretty_resource = "BMI" + self._name = pretty_resource + unit_type = FITBIT_RESOURCES_LIST[self.resource_type] + if unit_type == "": + split_resource = self.resource_type.split("/") + measurement_system = FITBIT_MEASUREMENTS[self.client.system] + unit_type = measurement_system[split_resource[-1]] + self._unit_of_measurement = unit_type + self._state = 0 + self.update() + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def unit_of_measurement(self): + """Return the unit of measurement of this entity, if any.""" + return self._unit_of_measurement + + @property + def icon(self): + """Icon to use in the frontend, if any.""" + return ICON + + # pylint: disable=too-many-branches + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Get the latest data from the Fitbit API and update the states.""" + container = self.resource_type.replace("/", "-") + response = self.client.time_series(self.resource_type, period="7d") + self._state = response[container][-1].get("value") + if self.resource_type == "activities/heart": + self._state = response[container][-1].get("restingHeartRate") + config_contents = { + "access_token": self.client.client.token["access_token"], + "refresh_token": self.client.client.token["refresh_token"], + "client_id": self.client.client.client_id, + "client_secret": self.client.client.client_secret, + "last_saved_at": int(time.time()) + } + if not config_from_file(self.config_path, config_contents): + _LOGGER.error("failed to save config file") diff --git a/requirements_all.txt b/requirements_all.txt index f15e2c4f5dc..ddfc5a0802f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -53,6 +53,9 @@ evohomeclient==0.2.5 # homeassistant.components.feedreader feedparser==5.2.1 +# homeassistant.components.sensor.fitbit +fitbit==0.2.2 + # homeassistant.components.notify.free_mobile freesms==0.1.0