def index(self, user=None, userData={}, methods=None, token=None, callerToken=None, **kwargs): """Main entry point - get Fitbit data for a single user""" if not user: self.igor.app.raiseHTTPError( "400 Fitbitplugin requires user argument") self.user = user self.token = token if not 'token' in userData: self.igor.app.raiseHTTPError( "403 Fitbitplugin requires 'token' plugindata for user '%s'" % user) oauthSettings = userData['token'] for k in KEYS_PER_USER: if not k in oauthSettings: self.igor.app.raiseHTTPError( "403 Fitbitplugin 'token' plugindata for user '%s' misses '%s'" % (user, k)) for k in KEYS_PER_APP: if not k in self.pluginData: self.igor.app.raiseHTTPError( "403 Fitbitplugin requires global plugindata '%s'" % k) oauthSettings[k] = self.pluginData[k] fb = Fitbit(refresh_cb=self._refresh, **oauthSettings) # Populate kwargs from userData, unless already specified in the parameters for k, v in list(userData.items()): if k != 'token' and k != 'methods' and not k in kwargs: kwargs[k] = v # Convert to strings (fitbit library doesn't like unicode) for k, v in list(kwargs.items()): kwargs[k] = v results = {} if methods == None: methods = userData.get('methods', 'get_bodyweight') methods = methods.split(',') for method in methods: if DEBUG: print('xxxjack calling method', method, 'with', kwargs) m = getattr(fb, method) try: item = m(**kwargs) except oauthlib.oauth2.rfc6749.errors.OAuth2Error as ex: descr = ex.description if not descr: descr = str(ex) self.igor.app.raiseHTTPError("502 Fitbit OAuth2 error: %s" % descr) except Exception as ex: print('Exception in fitbit.%s with args %s' % (method, repr(kwargs))) traceback.print_exc(file=sys.stdout) self.igor.app.raiseHTTPError("502 fitbit error %s" % repr(ex)) if DEBUG: print("xxxjack method", method, "returned", m) results.update(item) self.igor.databaseAccessor.put_key('sensors/%s/%s' % (self.pluginName, user), 'application/x-python-object', None, results, 'application/x-python-object', token, replace=True) return str(results)
def setup_platform( opp: OpenPeerPower, config: ConfigType, add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the Fitbit sensor.""" config_path = opp.config.path(FITBIT_CONFIG_FILE) if os.path.isfile(config_path): config_file: ConfigType = cast(ConfigType, load_json(config_path)) if config_file == DEFAULT_CONFIG: request_app_setup(opp, config, add_entities, config_path, discovery_info=None) return else: save_json(config_path, DEFAULT_CONFIG) request_app_setup(opp, config, add_entities, config_path, discovery_info=None) return if "fitbit" in _CONFIGURING: opp.components.configurator.request_done(_CONFIGURING.pop("fitbit")) access_token: str | None = config_file.get(ATTR_ACCESS_TOKEN) refresh_token: str | None = config_file.get(ATTR_REFRESH_TOKEN) expires_at: int | None = config_file.get(ATTR_LAST_SAVED_AT) if (access_token is not None and refresh_token is not None and expires_at is not None): authd_client = Fitbit( config_file.get(CONF_CLIENT_ID), config_file.get(CONF_CLIENT_SECRET), access_token=access_token, refresh_token=refresh_token, expires_at=expires_at, refresh_cb=lambda x: None, ) if int(time.time()) - expires_at > 3600: authd_client.client.refresh_token() unit_system = config.get(CONF_UNIT_SYSTEM) if unit_system == "default": authd_client.system = authd_client.user_profile_get( )["user"]["locale"] if authd_client.system != "en_GB": if opp.config.units.is_metric: authd_client.system = "metric" else: authd_client.system = "en_US" else: authd_client.system = unit_system dev = [] registered_devs = authd_client.get_devices() clock_format = config.get(CONF_CLOCK_FORMAT, DEFAULT_CLOCK_FORMAT) for resource in config.get(CONF_MONITORED_RESOURCES, FITBIT_DEFAULT_RESOURCES): # monitor battery for all linked FitBit devices if resource == "devices/battery": for dev_extra in registered_devs: dev.append( FitbitSensor( authd_client, config_path, resource, opp.config.units.is_metric, clock_format, dev_extra, )) else: dev.append( FitbitSensor( authd_client, config_path, resource, opp.config.units.is_metric, clock_format, )) add_entities(dev, True) else: oauth = FitbitOauth2Client(config_file.get(CONF_CLIENT_ID), config_file.get(CONF_CLIENT_SECRET)) redirect_uri = f"{get_url(opp)}{FITBIT_AUTH_CALLBACK_PATH}" fitbit_auth_start_url, _ = oauth.authorize_token_url( redirect_uri=redirect_uri, scope=[ "activity", "heartrate", "nutrition", "profile", "settings", "sleep", "weight", ], ) opp.http.register_redirect(FITBIT_AUTH_START, fitbit_auth_start_url) opp.http.register_view( FitbitAuthCallbackView(config, add_entities, oauth)) request_oauth_completion(opp)
def run_api_poller(): cfg_path = try_getenv('CONFIG_PATH') db_host = try_getenv('DB_HOST') db_port = try_getenv('DB_PORT') db_user = try_getenv('DB_USER') db_password = try_getenv('DB_PASSWORD') db_name = try_getenv('DB_NAME') redirect_url = try_getenv('CALLBACK_URL') units = try_getenv('UNITS', 'it_IT') # These are required vars, that we first try to load from file client_id = try_load_var(cfg_path, 'client_id') client_secret = try_load_var(cfg_path, 'client_secret') access_token = try_load_var(cfg_path, 'access_token') refresh_token = try_load_var(cfg_path, 'refresh_token') expires_at = try_load_var(cfg_path, 'expires_at') # If any of the required vars is not in file, try to read from env # If read, save if not client_id: client_id = try_getenv('CLIENT_ID') save_var(cfg_path, 'client_id', client_id) if not client_secret: client_secret = try_getenv('CLIENT_SECRET') save_var(cfg_path, 'client_secret', client_secret) if not access_token: access_token = try_getenv('ACCESS_TOKEN') save_var(cfg_path, 'access_token', access_token) if not refresh_token: refresh_token = try_getenv('REFRESH_TOKEN') save_var(cfg_path, 'refresh_token', refresh_token) if not expires_at: expires_at = try_cast_to_int(try_getenv('EXPIRES_AT')) save_var(cfg_path, 'expires_at', str(expires_at)) logger.debug( "client_id: %s, client_secret: %s, access_token: %s, refresh_token: %s, expires_at: %s", client_id, client_secret, access_token, refresh_token, expires_at) if not client_id: logging.critical("client_id missing, aborting!") sys.exit(1) if not client_secret: logging.critical("client_secret missing, aborting!") sys.exit(1) if not access_token: logging.critical("access_token missing, aborting!") sys.exit(1) if not refresh_token: logging.critical("refresh_token missing, aborting!") sys.exit(1) api_client = Fitbit(client_id=client_id, client_secret=client_secret, access_token=access_token, refresh_token=refresh_token, redirect_uri=redirect_url, refresh_cb=partial(write_updated_credentials, cfg_path), system=Fitbit.METRIC) user_profile = None while True: try: user_profile = api_client.user_profile_get() break except Timeout as ex: logger.warning('Request timed out, retrying in 15 seconds...') time.sleep(15) except HTTPServerError as ex: logger.warning( 'Server returned exception (5xx), retrying in 15 seconds (%s)', ex) time.sleep(15) except HTTPTooManyRequests as ex: # 150 API calls done, and python-fitbit doesn't provide the retry-after header, so stop trying # and allow the limit to reset, even if it costs us one hour logger.info('API limit reached, sleeping for 3610 seconds!') time.sleep(3610) except Exception as ex: logger.exception('Got some unexpected exception') raise member_since = user_profile.get('user', {}).get('memberSince', '1970-01-01') member_since_dt = parse(member_since, ignoretz=True) member_since_ts = parse(member_since, ignoretz=True).timestamp() logger.info('User is member since: %s (ts: %s)', member_since, member_since_ts) cur_day = datetime.utcnow() db_client = InfluxDBClient(db_host, db_port, db_user, db_password, db_name) for one_db in db_client.get_list_database(): if one_db['name'] == db_name: break else: db_client.create_database(db_name) db_client.close() # First try to fill any gaps: between User_member_since and first_ts, # and then between last_ts and cur_day while True: for meas, series_list in BASE_SERIES.items(): for series in series_list: resource = '{}/{}'.format(meas, series) if '_' in meas: resource = resource.replace('_', '/', 1) if resource == 'sleep/sleep': # Sleep is special, is its own main category resource = 'sleep' db_client = InfluxDBClient(db_host, db_port, db_user, db_password, db_name) key_series = series if isinstance(series_list, dict) and series_list.get(series): # Datapoints are retrieved with all keys in the same dict, so makes no sense to retrieve individual # series names. Use one series as the key series. key_series = series_list[series]['key_series'] first_ts = get_first_timestamp_for_measurement(db_client, meas, key_series, min_ts=cur_day) last_ts = get_last_timestamp_for_measurement(db_client, meas, key_series, min_ts=cur_day) profile_to_first = int( (first_ts - member_since_dt) / timedelta(days=1)) last_to_current = int((cur_day - last_ts) / timedelta(days=1)) logger.debug( 'key_series: %s, first_ts: %s, last_ts: %s, profile_to_first: %s, last_to_current: %s', key_series, first_ts, last_ts, profile_to_first, last_to_current) db_client.close() intervals_to_fetch = [] if profile_to_first > 1: append_between_day_series(intervals_to_fetch, member_since_dt, first_ts) if last_to_current > 1: append_between_day_series(intervals_to_fetch, last_ts, cur_day) if not intervals_to_fetch: logger.info( 'No gaps to fetch for %s, %s: fetching last day only', meas, series) intervals_to_fetch.append(( cur_day, cur_day, )) # DB can't be open here, because fitbit_fetch_datapoints can hang for a long time if meas == 'sleep': api_client.API_VERSION = '1.2' datapoints = fitbit_fetch_datapoints(api_client, meas, series, resource, intervals_to_fetch) if meas == 'sleep': api_client.API_ENDPOINT = '1' converted_dps = [] for one_d in datapoints: if not one_d: continue if isinstance(series_list, dict) and series_list.get(series): new_dps = series_list[series]['transform'](one_d) for one_dd in new_dps: converted_dps.append( create_api_datapoint_meas_series( one_dd['meas'], one_dd['series'], one_dd['value'], one_dd['dateTime'])) else: converted_dps.append( create_api_datapoint_meas_series( meas, series, one_d.get('value'), one_d.get('dateTime'))) db_client = InfluxDBClient(db_host, db_port, db_user, db_password, db_name) precision = 'h' if meas == 'sleep': precision = 's' logger.debug( 'Going to write %s points, key_series: %s, first_ts: %s, last_ts: %s, profile_to_first: %s, last_to_current: %s', len(converted_dps), key_series, first_ts, last_ts, profile_to_first, last_to_current) logger.debug('First 3: %s', converted_dps[:3]) logger.debug('Last 3: %s', converted_dps[-3:]) if not db_client.write_points(converted_dps, time_precision=precision, batch_size=2500): logger.critical( 'key_series: %s, first_ts: %s, last_ts: %s, profile_to_first: %s, last_to_current: %s', key_series, first_ts, last_ts, profile_to_first, last_to_current) raise Exception('Unable to write points!') db_client.close() logger.info('All series processed, sleeping for 4h') time.sleep(3610 * 4) sys.exit(0)
def setUp(self): self.fb = Fitbit('x', 'y')
def setUp(self): self.fb = Fitbit('x', 'y') self.fb_timeout = Fitbit('x', 'y', timeout=10) self.test_url = 'invalid://do.not.connect'
def run(): client_id, client_secret = _get_client_details() access_token, refresh_token, expires_at = _get_user_details() # print(f'Running Fitbit request with details: {client_id} {client_secret}' # f' {access_token} {refresh_token} {expires_at}') auth2_client = Fitbit(client_id, client_secret, oauth2=True, access_token=access_token, refresh_token=refresh_token, expires_at=expires_at, refresh_cb=refresh_callback) fitbit_url = FITBIT_API + _get_api_call(1) json_response = auth2_client.make_request(fitbit_url) _write_results(json_response,RESULT_FILE) length = len(json_response["activities-heart-intraday"]['dataset']) heart_min_data = json_response["activities-heart-intraday"]['dataset'] HR_hour_data = {} HR_min_data = {} for i in range(0,length): if(i%60 == 0): if heart_min_data[i]["time"].split(":")[0][0] == '0': HR_min_data[heart_min_data[i]["time"].split(":")[0][1]] = [heart_min_data[i]["value"]] else: HR_min_data[heart_min_data[i]["time"].split(":")[0]] = [heart_min_data[i]["value"]] else: if heart_min_data[i]["time"].split(":")[0][0] == '0': HR_min_data[heart_min_data[i]["time"].split(":")[0][1]].append(heart_min_data[i]["value"]) else: HR_min_data[heart_min_data[i]["time"].split(":")[0]].append(heart_min_data[i]["value"]) for i,j in HR_min_data.items(): HR_hour_data[i] = int(sum(j)/len(j)) print(HR_hour_data) fitbit_url = FITBIT_API + _get_api_call(2) json_response = auth2_client.make_request(fitbit_url) _write_results(json_response,RESULT_FILE2) sleep_data = {} for i in json_response["sleep"]: sleep_data[i['dateOfSleep']]= i['minutesAsleep'] print(sleep_data) fitbit_url = FITBIT_API + _get_api_call(3) json_response = auth2_client.make_request(fitbit_url) _write_results(json_response,RESULT_FILE3) calories = {} for date in json_response["activities-log-calories"]: calories[date['dateTime']]= int(date['value']) print(calories) print(json_response) fitbit_url = FITBIT_API + _get_api_call(4) json_response = auth2_client.make_request(fitbit_url) _write_results(json_response,RESULT_FILE4) steps_date = {} weekly_steps = {} print(json_response["activities-log-steps"]) for date in json_response["activities-log-steps"]: steps_date[date['dateTime']]= int(date['value']) print(steps_date) for i in steps_date: if i != 0: date = i weekday = datetime.datetime.strptime(date, '%Y-%m-%d').weekday() weekly_steps[weekdays[weekday]] = steps_date[i] print(weekly_steps)
def setup_platform( hass: HomeAssistant, config: ConfigType, add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the Fitbit sensor.""" config_path = hass.config.path(FITBIT_CONFIG_FILE) if os.path.isfile(config_path): config_file: ConfigType = cast(ConfigType, load_json(config_path)) if config_file == DEFAULT_CONFIG: request_app_setup(hass, config, add_entities, config_path, discovery_info=None) return else: save_json(config_path, DEFAULT_CONFIG) request_app_setup(hass, config, add_entities, config_path, discovery_info=None) return if "fitbit" in _CONFIGURING: hass.components.configurator.request_done(_CONFIGURING.pop("fitbit")) access_token: str | None = config_file.get(ATTR_ACCESS_TOKEN) refresh_token: str | None = config_file.get(ATTR_REFRESH_TOKEN) expires_at: int | None = config_file.get(ATTR_LAST_SAVED_AT) if (access_token is not None and refresh_token is not None and expires_at is not None): authd_client = Fitbit( config_file.get(CONF_CLIENT_ID), config_file.get(CONF_CLIENT_SECRET), access_token=access_token, refresh_token=refresh_token, expires_at=expires_at, refresh_cb=lambda x: None, ) if int(time.time()) - expires_at > 3600: authd_client.client.refresh_token() if (unit_system := config[CONF_UNIT_SYSTEM]) == "default": authd_client.system = authd_client.user_profile_get( )["user"]["locale"] if authd_client.system != "en_GB": if hass.config.units.is_metric: authd_client.system = "metric" else: authd_client.system = "en_US" else: authd_client.system = unit_system registered_devs = authd_client.get_devices() clock_format = config[CONF_CLOCK_FORMAT] monitored_resources = config[CONF_MONITORED_RESOURCES] entities = [ FitbitSensor( authd_client, config_path, description, hass.config.units.is_metric, clock_format, ) for description in FITBIT_RESOURCES_LIST if description.key in monitored_resources ] if "devices/battery" in monitored_resources: entities.extend([ FitbitSensor( authd_client, config_path, FITBIT_RESOURCE_BATTERY, hass.config.units.is_metric, clock_format, dev_extra, ) for dev_extra in registered_devs ]) add_entities(entities, True)
# if args['debug']: # logging.basicConfig(level = logging.DEBUG) # else: # logging.basicConfig(level=logging.INFO) # set up connection to INDX # password = getpass.getpass() # indx = IndxClient(args['address'], args['box'], args['user'], args['passwd'], "Fitbit Connector") # set up connection to Fitbit consumer_key = "9cc7928d03fa4e1a92eda0d01ede2297" consumer_secret = "340ea36a974e47738a335c0cccfe1fcf" # fitbit = Fitbit(consumer_key, consumer_secret, access_token_key, access_token_secret) fitbit = Fitbit(consumer_key, consumer_secret) if (fitbit.token == None): gotourl = fitbit.get_token_url() pin = raw_input("Please input you PIN: ") fitbit.get_token_with_pin(pin) fitbit_min = FitbitIntraDay(fitbit) # def get_fitbit_data(): # from_date = args['from_date'] # to_date = args['to_date'] # print '\nget activities tracker steps:\n' # return fitbit_ts.get_activities_tracker_steps(to_date, from_date) def transform_fitbit_response(response):
def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the Fitbit sensor.""" config_path = hass.config.path(config.get(CONF_FILENAME)) name = config.get(CONF_NAME) configuring_name = "fitbit" if name is None else "fitbit_" + name if os.path.isfile(config_path): config_file = load_json(config_path) if config_file == DEFAULT_CONFIG: request_app_setup(hass, config, add_entities, config_path, discovery_info=None) return False else: save_json(config_path, DEFAULT_CONFIG) request_app_setup(hass, config, add_entities, config_path, discovery_info=None) return False if configuring_name in _CONFIGURING: hass.components.configurator.request_done( _CONFIGURING.pop(configuring_name)) access_token = config_file.get(ATTR_ACCESS_TOKEN) refresh_token = config_file.get(ATTR_REFRESH_TOKEN) expires_at = config_file.get(ATTR_LAST_SAVED_AT) if None not in (access_token, refresh_token): authd_client = Fitbit( config_file.get(CONF_CLIENT_ID), config_file.get(CONF_CLIENT_SECRET), access_token=access_token, refresh_token=refresh_token, expires_at=expires_at, refresh_cb=lambda x: None, ) if int(time.time()) - expires_at > 3600: authd_client.client.refresh_token() unit_system = config.get(CONF_UNIT_SYSTEM) if unit_system == "default": authd_client.system = authd_client.user_profile_get( )["user"]["locale"] if authd_client.system != "en_GB": if hass.config.units.is_metric: authd_client.system = "metric" else: authd_client.system = "en_US" else: authd_client.system = unit_system dev = [] registered_devs = authd_client.get_devices() clock_format = config.get(CONF_CLOCK_FORMAT) for resource in config.get(CONF_MONITORED_RESOURCES): # monitor battery for all linked FitBit devices if resource == "devices/battery": for dev_extra in registered_devs: dev.append( FitbitSensor( authd_client, config_path, resource, name, hass.config.units.is_metric, clock_format, dev_extra, )) else: dev.append( FitbitSensor( authd_client, config_path, resource, name, hass.config.units.is_metric, clock_format, )) add_entities(dev, True) else: oauth = FitbitOauth2Client(config_file.get(CONF_CLIENT_ID), config_file.get(CONF_CLIENT_SECRET)) redirect_uri = f"{get_url(hass, prefer_external=True)}{FITBIT_AUTH_CALLBACK_PATH}" fitbit_auth_start_url, _ = oauth.authorize_token_url( redirect_uri=redirect_uri, scope=[ "activity", "heartrate", "nutrition", "profile", "settings", "sleep", "weight", ], ) hass.http.register_redirect(FITBIT_AUTH_START, fitbit_auth_start_url) hass.http.register_view( FitbitAuthCallbackView(config, add_entities, oauth)) request_oauth_completion(hass, configuring_name)
def setUp(self): self.fb = Fitbit(consumer_key='x', consumer_secret='y')