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 setup_garmin( options, config ): """ Setup the Garmin Connect credentials """ if options.key is None: options.key = input('Please enter your Garmin Connect username: '******'Please enter your Garmin Connect password: '******'garmin'): config.add_section('garmin') config.set('garmin', 'username', options.key) config.set('garmin', 'password', options.secret)
# 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: print("%d weights has been successfully updated to Garmin!" % (len(groups))) config.set('garmin','last_sync', str(next_sync)) elif service == 'smashrun': for m in reversed(groups): t = types['weight'] weight = m.get_measure(t) if weight: break print("Last weight from Nokia Health: %s kg taken at %s" % (weight, m.date))
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')
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(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")
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)
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: print('error') else: print('No Garmin username - skipping sync')