def sync(withings_username, withings_password, withings_shortname, garmin_username, garmin_password, fromdate, todate, no_upload, verbose): def verbose_print(s): if verbose: if no_upload: sys.stderr.write(s) else: sys.stdout.write(s) # Withings API withings = WithingsAccount(withings_username, withings_password) user = withings.get_user_by_shortname(withings_shortname) if not user: print 'could not find user: %s' % withings_shortname return #if not user.ispublic: # print 'user %s has not opened withings data' % withings_shortname # return startdate = int(time.mktime(fromdate.timetuple())) enddate = int(time.mktime(todate.timetuple())) + 86399 groups = user.get_measure_groups(startdate=startdate, enddate=enddate) # create fit file verbose_print('generating fit file...\n') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() for group in groups: # get extra physical measurements from measurements import Measurements measurements = Measurements() dt = group.get_datetime() weight = group.get_weight() fat_ratio = group.get_fat_ratio() muscle_mass = group.get_muscle_mass() bone_mass=group.get_bone_mass() hydro = group.get_hydro() # mass_hydro to percent_hydro conversion ratio = 100 / weight hydro = hydro * ratio bone_mass = group.get_bone_mass() fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio, percent_hydration=hydro, muscle_mass=muscle_mass, bone_mass=bone_mass, ) verbose_print('appending weight scale record... %s %skg %s%%\n' % (dt, weight, fat_ratio)) fit.finish() if no_upload: sys.stdout.write(fit.getvalue()) return verbose_print("Fit file: " + fit.getvalue()) # garmin connect garmin = GarminConnect() session = garmin.login(garmin_username, garmin_password) verbose_print('attempting to upload fit file...\n') r = garmin.upload_file(fit.getvalue(), session) if r: verbose_print('weight.fit has been successfully uploaded!\n')
print("Their is no new measurement to sync.") save_config() sys.exit(0); if service == 'garmin': next_sync = groups[-1].date.timestamp # Do not repeatidly sync the same value if next_sync == last_sync: print('Last measurement was already synced') save_config() sys.exit(0) # create fit file fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() fit.write_device_info(timestamp=next_sync) for m in groups: weight = m.get_measure(types['weight']); if weight: fit.write_weight_scale(timestamp=m.date.timestamp, weight=weight, percent_fat=m.get_measure(types['fat_ratio']), percent_hydration=m.get_measure(types['hydration']), bone_mass=m.get_measure(types['bone_mass']), muscle_mass=m.get_measure(types['muscle_mass'])) fit.finish() garmin = GarminConnect() session = garmin.login(config.get('garmin','username'), config.get('garmin','password')) r = garmin.upload_file(fit.getvalue(), session) if r:
def sync(garmin_username, garmin_password, trainerroad_username, trainerroad_password, fromdate, todate, no_upload, verbose): def verbose_print(s): if verbose: if no_upload: sys.stderr.write(s) else: sys.stdout.write(s) # Withings API withings = WithingsAccount() startdate = int(time.mktime(fromdate.timetuple())) enddate = int(time.mktime(todate.timetuple())) + 86399 groups = withings.getMeasurements(startdate=startdate, enddate=enddate) # create fit file verbose_print('generating fit file...\n') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() last_dt = None last_weight = 0 for group in groups: # get extra physical measurements dt = group.get_datetime() weight = group.get_weight() fat_ratio = group.get_fat_ratio() muscle_mass = group.get_muscle_mass() hydration = group.get_hydration() bone_mass = group.get_bone_mass() fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio, percent_hydration=(hydration * 100.0 / weight) if (hydration and weight) else None, bone_mass=bone_mass, muscle_mass=muscle_mass) verbose_print('appending weight scale record... %s %skg %s%%\n' % (dt, weight, fat_ratio)) last_dt = dt last_weight = weight fit.finish() # garmin connect if trainerroad_username and last_weight > 0: print('Trainerroad username set -- attempting to sync') print(" Last weight {}".format(last_weight)) print(" Measured {}".format(last_dt)) tr = trainerroad.TrainerRoad(trainerroad_username, trainerroad_password) tr.connect() print("Current TrainerRoad weight: {} kg ".format(tr.weight)) print("Updating TrainerRoad weight to {} kg".format(last_weight)) tr.weight = round(last_weight, 1) tr.disconnect() print("TrainerRoad update done!\n") else: print('No Trainerroad username or a new measurement - skipping sync') if no_upload: sys.stdout.buffer.write(fit.getvalue()) return if garmin_username: garmin = GarminConnect() session = garmin.login(garmin_username, garmin_password) verbose_print('attempting to upload fit file...\n') r = garmin.upload_file(fit.getvalue(), session) if r: print("Fit file uploaded to Garmin Connect") else: print('No Garmin username - skipping sync\n')
def sync(csv_file, garmin_username, garmin_password, fromdate, todate, no_upload, verbose): def verbose_print(s): if verbose: if no_upload: sys.stderr.write(s) else: sys.stdout.write(s) if csv_file == '': verbose_print("--csv_file is required\n") exit(1) if not(os.path.isfile(csv_file)): verbose_print("File " + csv_file + " not found\n") exit(1) # OpenScale CSV osc = OpenScaleCSV() osc.load(csv_file) startdate = int(time.mktime(fromdate.timetuple())) enddate = int(time.mktime(todate.timetuple())) + 86399 groups = [] for ix in range(0, osc.records()): item = osc.record(ix) dt = int(time.mktime(item['dateTime'].timetuple())) if dt < startdate: continue if dt > enddate: continue groups.append(item) # create fit file verbose_print('generating fit file...\n') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() for group in groups: dt = group['dateTime'] weight = group['weight'] fat_ratio = group['fat'] fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio) verbose_print('appending weight scale record... %s %skg %s%%\n' % (dt, weight, fat_ratio)) fit.finish() if no_upload: sys.stdout.write(fit.getvalue()) return # create temporary file fi, fn = mkstemp() fn = fn + '.fit' fp = open(fn, 'w') fp.write(fit.getvalue()) fp.close() # garmin connect verbose_print('attempting to upload fit file...\n') workflow = Workflow(paths=[fn], username=garmin_username, password=garmin_password) workflow.run()
def sync(garmin_username, garmin_password, fromdate, todate, no_upload, verbose): def verbose_print(s): if verbose: if no_upload: sys.stderr.write(s) else: sys.stdout.write(s) if len(garmin_username) == 0 or len(garmin_password) == 0: print("Garmin username or password not set!") return # Withings API withings = WithingsAccount() startdate = int(time.mktime(fromdate.timetuple())) enddate = int(time.mktime(todate.timetuple())) + 86399 groups = withings.getMeasurements(startdate=startdate, enddate=enddate) # create fit file verbose_print('generating fit file...\n') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() for group in groups: # get extra physical measurements dt = group.get_datetime() weight = group.get_weight() fat_ratio = group.get_fat_ratio() muscle_mass = group.get_muscle_mass() hydration = group.get_hydration() bone_mass = group.get_bone_mass() fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio, percent_hydration=(hydration * 100.0 / weight) if (hydration and weight) else None, bone_mass=bone_mass, muscle_mass=muscle_mass) verbose_print('appending weight scale record... %s %skg %s%%\n' % (dt, weight, fat_ratio)) fit.finish() if no_upload: sys.stdout.buffer.write(fit.getvalue()) return #out_file = open('test.fit', 'wb') #out_file.write(fit.getvalue()) # verbose_print("Fit file: " + fit.getvalue()) # garmin connect garmin = GarminConnect() session = garmin.login(garmin_username, garmin_password) verbose_print('attempting to upload fit file...\n') r = garmin.upload_file(fit.getvalue(), session) if r: print("Fit file uploaded to Garmin Connect")
def sync(garmin_username, garmin_password, fromdate, todate, no_upload, verbose): def verbose_print(s): if verbose: if no_upload: sys.stderr.write(s) else: sys.stdout.write(s) if len(garmin_username) == 0 or len(garmin_password) == 0: print("Garmin username or password not set!") return # Withings API withings = WithingsAccount() startdate = int(time.mktime(fromdate.timetuple())) enddate = int(time.mktime(todate.timetuple())) + 86399 groups = withings.getMeasurements(startdate=startdate, enddate=enddate) # create fit file verbose_print('generating fit file...\n') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() for group in groups: # get extra physical measurements dt = group.get_datetime() weight = group.get_weight() fat_ratio = group.get_fat_ratio() muscle_mass = group.get_muscle_mass() hydration = group.get_hydration() bone_mass = group.get_bone_mass() fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio, percent_hydration=(hydration*100.0/weight) if (hydration and weight) else None, bone_mass=bone_mass, muscle_mass=muscle_mass ) verbose_print('appending weight scale record... %s %skg %s%%\n' % (dt, weight, fat_ratio)) fit.finish() if no_upload: sys.stdout.buffer.write(fit.getvalue()) return #out_file = open('test.fit', 'wb') #out_file.write(fit.getvalue()) # verbose_print("Fit file: " + fit.getvalue()) # garmin connect garmin = GarminConnect() session = garmin.login(garmin_username, garmin_password) verbose_print('attempting to upload fit file...\n') r = garmin.upload_file(fit.getvalue(), session) if r: print("Fit file uploaded to Garmin Connect")
else: print( "You must provide the name of the service to setup. Available services are: nokia, garmin, smashrun." ) sys.exit(1) if service == 'garmin': # Do not repeatidly sync the same value if config.has_option('garmin', 'last_sync'): if m.date.timestamp == int(config.get('garmin', 'last_sync')): print('Last measurement was already synced') sys.exit(0) # create fit file fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() fit.write_device_info(timestamp=m.date.timestamp) fit.write_weight_scale(timestamp=m.date.timestamp, weight=weight) fit.finish() garmin = GarminConnect() session = garmin.login(config.get('garmin', 'username'), config.get('garmin', 'password')) r = garmin.upload_file(fit.getvalue(), session) if r: print('Weight has been successfully updated to Garmin!') config.set('garmin', 'last_sync', str(m.date.timestamp))
def mqtt_on_message(client, userdata, msg): logger.info(f'Received payload: {msg.payload}') try: data = json.loads(msg.payload) except json.decoder.JSONDecodeError: logger.error('Could not parse JSON, ignoring') return # At this point, the payload is valid: let's ack mqttPub.single( config['mqtt']['topic_ack'], payload="1", # TODO: hard-coded, leave as is or ok? hostname=config['mqtt']['host'], port=config['mqtt']['port'], auth={ 'username': config['mqtt']['username'], 'password': config['mqtt']['password'] }) # Has this entry been processed before? (MQTT messages are retained) if check_entry_already_processed(data): logger.info('Data is stale, ignoring') return else: logger.info('Data looks fresh, continuing') height = float(config['garmin']['height']) # Weight has to be within the 10kg-200kg range. Metrics calculation will # fail if not within that range. Probably a bogus measurement anyway. Just # move on. weight = float(data.get('Weight', 0)) if not weight or not 10 < weight < 200: logger.error('No weight data or weight value bogus, ignoring') return # Compute metrics if both weight and impedance are present. # Weight is already checked, additional check for impedance. if data.get('Impedance'): metrics = bodyMetrics( weight=weight, height=height, age=float( (datetime.date.today() - config['garmin']['dateOfBirth']).days / 365.25), sex=config['garmin']['sex'], impedance=float(data['Impedance'])) dtFormat = '%Y %m %d %H %M %S' try: dt = datetime.datetime.strptime(data.get('Timestamp'), dtFormat) except (TypeError, ValueError): # Cannot parse timestamp. Assuming measurement was done just now. dt = datetime.datetime.now() # Data dict prep metrics_dict = { 'timestamp': dt, 'weight': metrics.weight, 'bmi': metrics.getBMI(), 'percent_fat': metrics.getFatPercentage(), 'percent_hydration': metrics.getWaterPercentage(), 'visceral_fat_mass': metrics.getVisceralFat(), 'bone_mass': metrics.getBoneMass(), 'muscle_mass': metrics.getMuscleMass(), 'basal_met': metrics.getBMR(), } # Prepare Garmin data object fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() fit.write_device_info(timestamp=dt) if metrics: fit.write_weight_scale(**metrics_dict) else: fit.write_weight_scale(timestamp=dt, weight=metrics.weight, bmi=weight / (height / 100)**2) fit.finish() # Local save: HA sensor file (file contains the last entry and that's it) with open(config['last_meas'], 'w') as fp: json.dump(metrics_dict, fp, default=str) # Local save: full history try: with open(config['full_meas'], 'r') as fp: full_meas = json.load(fp) except FileNotFoundError: full_meas = dict(entries=[]) if not any(entry['timestamp'] == metrics_dict.pop('timestamp', None) for entry in full_meas['entries']): new_entry = {'timestamp': dt, 'data': metrics_dict} full_meas['entries'].append(new_entry) with open(config['full_meas'], 'w') as fp: json.dump(full_meas, fp, indent=4, default=str) garmin = GarminConnect() try: garminSession = garmin.login(config['garmin']['username'], config['garmin']['password']) except (requests.exceptions.ConnectionError, APIException): logger.error('Could not connect to Garmin Connect') return req = garmin.upload_file(fit.getvalue(), garminSession) if req: logger.info('Upload to Garmin succeeded') else: logger.info('Upload to Garmin failed') # Local save: last timestamp info (for `check_entry_already_processed`) with open(config['last_ts'], 'w') as fp: json.dump(data, fp)
'physique_rating': None, } for key, value in values.iteritems(): values[key] = raw_float('Enter %s: ' % key.replace('_', ' ')) if (values['weight'] and values['percent_fat'] and values['muscle_mass'] and not values['bone_mass']): calc_bone_mass = raw_input('Approximate bone mass' ' from other settings? (y/N) ') if calc_bone_mass == 'y': fat_weight = values['weight'] * values['percent_fat'] / 100 calculated = values['weight'] - values['muscle_mass'] - fat_weight values['bone_mass'] = max(0, calculated) timestamp = raw_input('Time (e.g. 2015-01-31-23-01): ') try: values['timestamp'] = datetime.strptime(timestamp, '%Y-%m-%d-%H-%M') except: print '- Date not recognized, defaulting to now' values['timestamp'] = datetime.now() fit = FitEncoder_Weight() fit.write_weight_scale(**values) fit.finish() a = open('weight-scale_%s.fit' % values['timestamp'].strftime('%Y-%m-%d-%H-%M'), 'w') a.write(fit.get_value())
# 'visceral_fat_mass': None, # 'visceral_fat_rating': None, # 'physique_rating': None, } if len(sys.argv) > 2: timestamp = sys.argv[2] else: values['timestamp'] = datetime.now() try: values['timestamp'] = datetime.strptime(timestamp, '%Y-%m-%d-%H-%M') except: print('- Date not recognized, defaulting to now') values['timestamp'] = datetime.now() fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() fit.write_weight_scale(**values) fit.finish() if garmin_username: garmin = GarminConnect() session = garmin.login(garmin_username, garmin_password) print(session) print('attempting to upload fit file...') r = garmin.upload_file(fit.getvalue(), session) print(r) if r: print('Fit file uploaded to Garmin Connect') else:
def sync(withings_username, withings_password, withings_shortname, garmin_username, garmin_password, fromdate, todate, no_upload, verbose): def verbose_print(s): if verbose: if no_upload: sys.stderr.write(s) else: sys.stdout.write(s) # Withings API withings = WithingsAccount(withings_username, withings_password) user = withings.get_user_by_shortname(withings_shortname) if not user: print 'could not find user: %s' % withings_shortname return if not user.ispublic: print 'user %s has not opened withings data' % withings_shortname return startdate = int(time.mktime(fromdate.timetuple())) enddate = int(time.mktime(todate.timetuple())) + 86399 groups = user.get_measure_groups(startdate=startdate, enddate=enddate) # create fit file verbose_print('generating fit file...\n') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() for group in groups: # get extra physical measurements from measurements import Measurements measurements = Measurements() dt = group.get_datetime() weight = group.get_weight() fat_ratio = group.get_fat_ratio() fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio, percent_hydration=measurements.getPercentHydration() ) verbose_print('appending weight scale record... %s %skg %s%%\n' % (dt, weight, fat_ratio)) fit.finish() if no_upload: sys.stdout.write(fit.getvalue()) return # garmin connect garmin = GarminConnect() cookie = garmin.login(garmin_username, garmin_password) verbose_print('attempting to upload fit file...\n') r = garmin.upload_file(fit.getvalue(), cookie) if r: verbose_print('weight.fit has been successfully uploaded!\n')
raise GenerateError('invalid username or password') raise if not user: raise GenerateError('could not find user: %s' % shortname) if not user.ispublic: raise GenerateError('user %s has not opened withings data' % shortname) startdate = strtotimestamp(request.form.get('startdate')) enddate = strtotimestamp(request.form.get('enddate')) if enddate: enddate += 86399 # 11:59:59 groups = user.get_measure_groups(startdate=startdate, enddate=enddate) if len(groups) == 0: raise GenerateError('no weight scale data is available') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() for group in groups: dt = group.get_datetime() weight = group.get_weight() fat_ratio = group.get_fat_ratio() fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio) fit.finish() fit.buf.seek(0) return fit.buf def strtotimestamp(s): try:
next_sync = groups[-1].date.timestamp # Do not repeatidly sync the same value if next_sync == last_sync: print('Last measurement was already synced') save_config() sys.exit(0) # Get height for BMI calculation height = None m = client_nokia.get_measures(limit=1, meastype=types['height']) if len(m): height = m[0].get_measure(types['height']) # create fit file fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() fit.write_device_info(timestamp=next_sync) for m in groups: weight = m.get_measure(types['weight']) if weight: hyd_percent = None fat = None bone = None muscle = None if m.get_measure(types['fat_ratio']): fat = m.get_measure(types['fat_ratio'])
def sync(withings_username, withings_password, withings_shortname, garmin_username, garmin_password, fromdate, todate, no_upload, verbose): def verbose_print(s): if verbose: if no_upload: sys.stderr.write(s) else: sys.stdout.write(s) # Withings API withings = WithingsAccount(withings_username, withings_password) user = withings.get_user_by_shortname(withings_shortname) if not user: print 'could not find user: %s' % withings_shortname return if not user.ispublic: print 'user %s has not opened withings data' % withings_shortname return startdate = int(time.mktime(fromdate.timetuple())) enddate = int(time.mktime(todate.timetuple())) + 86399 groups = user.get_measure_groups(startdate=startdate, enddate=enddate) # create fit file verbose_print('generating fit file...\n') fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() for group in groups: dt = group.get_datetime() weight = group.get_weight() fat_ratio = group.get_fat_ratio() fit.write_device_info(timestamp=dt) fit.write_weight_scale(timestamp=dt, weight=weight, percent_fat=fat_ratio) verbose_print('appending weight scale record... %s %skg %s%%\n' % (dt, weight, fat_ratio)) fit.finish() if no_upload: sys.stdout.write(fit.getvalue()) return # garmin connect garmin = GarminConnect() garmin.login(garmin_username, garmin_password) verbose_print('attempting to upload fit file...\n') r = garmin.upload_file(fit.getvalue()) if r: verbose_print('weight.fit has been successfully uploaded!\n')
def nokia_sync(force=False): config = get_config() n = config['nokia'] creds = NokiaCredentials(n['access_token'], n['token_expiry'], n['token_type'], n['refresh_token'], n['user_id'], n['client_id'], n['consumer_secret']) nokia_client = NokiaApi(creds, refresh_cb=nokia_refresh_cb) measures = nokia_client.get_measures() measure = measures[0] logger.info('Recieved {} measurements'.format(len(measures))) # Now check if we need to update last_update = max([m.date.timestamp for m in measures]) logger.info('Last measurement at {}'.format(last_update)) logger.info('Last update at {}'.format(config['nokia']['last_update'])) if (config['nokia']['last_update'] >= last_update) and not force: logger.info('No new weight updates') return measures msg = '' fit = FitEncoder_Weight() fit.write_file_info() fit.write_file_creator() fit.write_device_info(datetime.timestamp(datetime.now())) for measure in measures: if (config['nokia']['last_update'] < measure.date.timestamp) or force: if measure.weight is not None: bmi = measure.weight / config['nokia']['height']**2 msg += 'New measurement at {} ({})\n'.format( str(measure.date.datetime), measure.date.humanize()) msg += 'New weight = {} kg\n'.format(measure.weight) msg += 'New fat ratio= {} %\n'.format(measure.fat_ratio) msg += 'New hydration = {} %\n'.format(measure.hydration) msg += 'New bone mass = {} kg\n'.format(measure.bone_mass) msg += 'New muscle mass = {} kg\n'.format(measure.muscle_mass) msg += 'Calculated BMI = {} kg.m^-2\n'.format(bmi) for m in msg.splitlines(): logger.info(m) # Sync Garmin logger.info('Syncing weight of {} with GARMIN.'.format( measure.weight)) fit.write_weight_scale(timestamp=measure.date.timestamp, weight=measure.weight, percent_fat=measure.fat_ratio, percent_hydration=measure.hydration, bone_mass=measure.bone_mass, muscle_mass=measure.muscle_mass, bmi=bmi) fit.finish() with GarminClient(config['garmin']['username'], config['garmin']['password']) as client: client.upload_activity(io.BytesIO(fit.getvalue()), 'fit') # Sync Strava measure = measures[0] ts = datetime.timestamp(datetime.now()) ts -= (config['nokia']['weight_int'] * 86400) weight = [m.weight for m in measures if m.date.timestamp >= ts] logger.info("Averaging {} weight measurements".format(len(weight))) weight = mean(weight) if (config['nokia']['last_update'] != measure.date.timestamp) or force: logger.info('Syncing weight of {} with STRAVA.'.format(measure.weight)) strava = Strava(config['strava']) strava_token = strava.connect() config['strava'] = strava_token strava.client.update_athlete(weight=weight) msg += 'Synced weight of {} with Strava\n'.format(measure.weight) config = get_config() config['nokia']['last_update'] = max([m.date.timestamp for m in measures]) write_config(config) send_email('New Weight Sync', msg) return measures