예제 #1
0
    def test_cycling_freestyle_smoketest(self):
        # Setup
        workout_data = self.loadTestData(
            "peloton_workout_cycling_freestyle.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_cycling_freestyle.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_cycling_freestyle.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "27 sec Just Ride"
        assert filename == "1595374979-27 sec Just Ride-88963f6daf89445387da4ee2e26015f9.tcx"
        assert garmin_activity_type == "indoor_cycling"
        assert os.path.exists(os.path.join(output_directory, filename))

        tcx = self.loadOutputTCX(os.path.join(output_directory, filename))
        TCX.assertTcxSportMatches("Biking", tcx)
        TCX.assertTcxIdMatches(workout_data, tcx)
        TCX.assertTcxLapStartTimeMatches(workout_data, tcx)
        TCX.assertTcxTotalTimeSecondsMatches(workout_data, tcx)
        TCX.assertTcxMaximumSpeedMatches(workout_samples, tcx)
        TCX.assertTcxCaloriesMatches(workout_summary, tcx)
        TCX.assertTcxAvgHeartRateMatches(workout_summary, tcx)
        TCX.assertTcxAvgSpeedMatches(workout_samples, tcx)
        TCX.assertTcxMaxBikeCadenceMatches(workout_summary, tcx)
        TCX.assertTcxAvgWattsMatches(workout_summary, tcx)
        TCX.assertTcxMaxWattsMatches(workout_summary, tcx)
예제 #2
0
    def test_cycling_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_cycling.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_cycling.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_cycling.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "20 min HIIT Ride with Denis Morton"
        assert filename == "1586208689-20 min HIIT Ride with Denis Morton-6c4d525d20134c74b7395991ed6912ce.tcx"
        assert garmin_activity_type == "indoor_cycling"
        assert os.path.exists(os.path.join(output_directory, filename))

        tcx = self.loadOutputTCX(os.path.join(output_directory, filename))
        TCX.assertTcxSportMatches("Biking", tcx)
        TCX.assertTcxIdMatches(workout_data, tcx)
        TCX.assertTcxLapStartTimeMatches(workout_data, tcx)
        TCX.assertTcxTotalTimeSecondsMatches(workout_data, tcx)
        TCX.assertTcxMaximumSpeedMatches(workout_samples, tcx)
        TCX.assertTcxCaloriesMatches(workout_summary, tcx)
        TCX.assertTcxAvgHeartRateMatches(workout_summary, tcx)
        TCX.assertTcxAvgSpeedMatches(workout_samples, tcx)
        TCX.assertTcxMaxBikeCadenceMatches(workout_summary, tcx)
        TCX.assertTcxAvgWattsMatches(workout_summary, tcx)
        TCX.assertTcxMaxWattsMatches(workout_summary, tcx)
예제 #3
0
    def test_strength_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_strength.json")
        workout_summary = self.loadTestData("peloton_workoutsummary_strength.json")
        workout_samples = self.loadTestData("peloton_workoutsamples_strength.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(workout_data, workout_summary, workout_samples, output_directory)
        
        # Assert
        assert title == "10 min Bodyweight Strength with Becs Gentry"
        assert filename == "1589907174-10 min Bodyweight Strength with Becs Gentry-38583cbc0e434e54a2eb91be1a770e01.tcx"
        assert garmin_activity_type == "strength_training"
        assert os.path.exists(os.path.join(output_directory, filename))

        tcx = self.loadOutputTCX(os.path.join(output_directory, filename))
        TCX.assertTcxSportMatches("Other", tcx)
        TCX.assertTcxIdMatches(workout_data, tcx)
        TCX.assertTcxLapStartTimeMatches(workout_data, tcx)
        TCX.assertTcxTotalTimeSecondsMatches(workout_data, tcx)
        TCX.assertTcxMaximumSpeedMatches(workout_samples, tcx)
        TCX.assertTcxCaloriesMatches(workout_summary, tcx)
        TCX.assertTcxAvgHeartRateMatches(workout_summary,tcx)
        TCX.assertTcxMaxBikeCadenceMatches(workout_summary, tcx)
        TCX.assertTcxAvgWattsMatches(workout_summary, tcx)
        TCX.assertTcxMaxWattsMatches(workout_summary, tcx)
예제 #4
0
    def test_running_outdoor_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_running_outdoor.json")
        workout_summary = self.loadTestData("peloton_workoutsummary_running_outdoor.json")
        workout_samples = self.loadTestData("peloton_workoutsamples_running_outdoor.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(workout_data, workout_summary, workout_samples, output_directory)
        
        # Assert
        assert title == "20 min Walk + Run with Olivia Amato"
        assert filename == "1574980432-20 min Walk + Run with Olivia Amato-af25d72ea4c0400daeac2707fc30994f.tcx"
        assert garmin_activity_type == "walking"
        assert os.path.exists(os.path.join(output_directory, filename))

        tcx = self.loadOutputTCX(os.path.join(output_directory, filename))
        TCX.assertTcxSportMatches("Running", tcx)
        TCX.assertTcxIdMatches(workout_data, tcx)
        TCX.assertTcxLapStartTimeMatches(workout_data, tcx)
        TCX.assertTcxTotalTimeSecondsMatches(workout_data, tcx)
        TCX.assertTcxMaximumSpeedMatches(workout_samples, tcx)
        TCX.assertTcxCaloriesMatches(workout_summary, tcx)
        TCX.assertTcxAvgHeartRateMatches(workout_summary,tcx)
        TCX.assertTcxMaxBikeCadenceMatches(workout_summary, tcx)
        TCX.assertTcxAvgWattsMatches(workout_summary, tcx)
        TCX.assertTcxMaxWattsMatches(workout_summary, tcx)
예제 #5
0
    def test_running_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_running.json")
        workout_summary = self.loadTestData("peloton_workoutsummary_running.json")
        workout_samples = self.loadTestData("peloton_workoutsamples_running.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(workout_data, workout_summary, workout_samples, output_directory)
        
        # Assert
        assert title == "20 min Pop Fun Run with Olivia Amato"
        assert filename == "1565299850-20 min Pop Fun Run with Olivia Amato-63eef26a23744af295f14006811b159b.tcx"
        assert garmin_activity_type == "treadmill_running"
        assert os.path.exists(os.path.join(output_directory, filename))

        tcx = self.loadOutputTCX(os.path.join(output_directory, filename))
        TCX.assertTcxSportMatches("Running", tcx)
        TCX.assertTcxIdMatches(workout_data, tcx)
        TCX.assertTcxLapStartTimeMatches(workout_data, tcx)
        TCX.assertTcxTotalTimeSecondsMatches(workout_data, tcx)
        TCX.assertTcxMaximumSpeedMatches(workout_samples, tcx)
        TCX.assertTcxCaloriesMatches(workout_summary, tcx)
        TCX.assertTcxAvgHeartRateMatches(workout_summary,tcx)
        TCX.assertTcxMaxBikeCadenceMatches(workout_summary, tcx)
        TCX.assertTcxAvgWattsMatches(workout_summary, tcx)
        TCX.assertTcxMaxWattsMatches(workout_summary, tcx)
예제 #6
0
    def test_cycling_km_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_cycling_km.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_cycling_km.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_cycling_km.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "20 min 2010s Pop Ride with Tunde Oyeneyin"
        assert filename == "1598294050-20 min 2010s Pop Ride with Tunde Oyeneyin-6a8b9725f87346b9a84c917c32a02df6.tcx"
        assert garmin_activity_type == "indoor_cycling"
        assert os.path.exists(os.path.join(output_directory, filename))

        tcx = self.loadOutputTCX(os.path.join(output_directory, filename))
        TCX.assertTcxSportMatches("Biking", tcx)
        TCX.assertTcxIdMatches(workout_data, tcx)
        TCX.assertTcxLapStartTimeMatches(workout_data, tcx)
        TCX.assertTcxTotalTimeSecondsMatches(workout_data, tcx)
        TCX.assertTcxMaximumSpeedMatches(workout_samples, tcx)
        TCX.assertTcxCaloriesMatches(workout_summary, tcx)
        TCX.assertTcxAvgHeartRateMatches(workout_summary, tcx)
        TCX.assertTcxAvgSpeedMatches(workout_samples, tcx)
        TCX.assertTcxMaxBikeCadenceMatches(workout_summary, tcx)
        TCX.assertTcxAvgWattsMatches(workout_summary, tcx)
        TCX.assertTcxMaxWattsMatches(workout_summary, tcx)
예제 #7
0
    def run(config):
        numActivities = config.numActivities
        logger = config.logger
        pelotonClient = pelotonApi.PelotonApi(config.peloton_email, config.peloton_password)
        database = TinyDB('database.json')
        garminUploadHistoryTable = database.table('garminUploadHistory')

        if numActivities is None:
            numActivities = input("How many past activities do you want to grab?  ")

        logger.info("Get latest " + str(numActivities) + " workouts.")
        workouts = pelotonClient.getXWorkouts(numActivities)
        
        for w in workouts:
            workoutId = w["id"]
            logger.info("Get workout: {}".format(str(workoutId)))

            if w["status"] != "COMPLETE":
                logger.info("Workout status: {} - skipping".format(w["status"]))
                continue

            workout = pelotonClient.getWorkoutById(workoutId)

            logger.info("Get workout samples")
            workoutSamples = pelotonClient.getWorkoutSamplesById(workoutId)

            logger.info("Get workout summary")
            workoutSummary = pelotonClient.getWorkoutSummaryById(workoutId)

            try:
                title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(workout, workoutSummary, workoutSamples, config.output_directory)
                logger.info("Writing TCX file: " + filename)
            except Exception as e:
                logger.error("Failed to write TCX file for workout {} - Exception: {}".format(workoutId, e))

            if config.uploadToGarmin:
                try:
                    uploadItem = Query()
                    workoutAlreadyUploaded = garminUploadHistoryTable.contains(uploadItem.workoutId == workoutId)
                    if workoutAlreadyUploaded:
                        logger.info("Workout already uploaded to garmin, skipping...")
                        continue

                    logger.info("Uploading workout to Garmin")
                    fileToUpload = [config.output_directory + "/" + filename]
                    garminClient.uploadToGarmin(fileToUpload, config.garmin_email, config.garmin_password, garmin_activity_type.lower(), title)
                    garminUploadHistoryTable.insert({'workoutId': workoutId, 'title': title, 'uploadDt': datetime.now().strftime("%Y-%m-%d %H:%M:%S")})
                except Exception as e:
                    logger.error("Failed to upload to Garmin: {}".format(e))
                    database.close()

        logger.info("Done!")
        logger.info("Your Garmin TCX files can be found in the Output directory: " + config.output_directory)

        if config.pause_on_finish == "true":
            input("Press the <ENTER> key to continue...")
예제 #8
0
    def test_can_parse_workout_title_with_accented_characters(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_cycling.json")
        workout_data["ride"]["title"] = "5 min Beyoncé All-Star Cool Down Ride"
        workout_data["ride"]["instructor"]["name"] = "Robin Arzón"
        workout_summary = self.loadTestData("peloton_workoutsummary_cycling.json")
        workout_samples = self.loadTestData("peloton_workoutsamples_cycling.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(workout_data, workout_summary, workout_samples, output_directory)
        
        # Assert
        assert title == "5 min Beyonce All-Star Cool Down Ride with Robin Arzon"
        assert filename == "1607634579-5 min Beyonce All-Star Cool Down Ride with Robin Arzon-d49cc8314b4e4f7ca1726394a90f6757.tcx"
예제 #9
0
    def test_running_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_running.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_running.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_running.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "20 min Pop Fun Run with Olivia Amato"
        assert filename == "1565299850-20 min Pop Fun Run with Olivia Amato-63eef26a23744af295f14006811b159b.tcx"
        assert garmin_activity_type == "Running"
        assert os.path.exists(os.path.join(output_directory, filename))
예제 #10
0
    def test_strength_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_strength.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_strength.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_strength.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "10 min Bodyweight Strength with Becs Gentry"
        assert filename == "1589907174-10 min Bodyweight Strength with Becs Gentry-38583cbc0e434e54a2eb91be1a770e01.tcx"
        assert garmin_activity_type == "Other"
        assert os.path.exists(os.path.join(output_directory, filename))
예제 #11
0
    def test_cycling_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_cycling.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_cycling.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_cycling.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "20 min HIIT Ride with Denis Morton"
        assert filename == "1586208689-20 min HIIT Ride with Denis Morton-6c4d525d20134c74b7395991ed6912ce.tcx"
        assert garmin_activity_type == "Biking"
        assert os.path.exists(os.path.join(output_directory, filename))
예제 #12
0
    def test_running_outdoor_smoketest(self):
        # Setup
        workout_data = self.loadTestData(
            "peloton_workout_running_outdoor.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_running_outdoor.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_running_outdoor.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "20 min Walk + Run with Olivia Amato"
        assert filename == "1574980432-20 min Walk + Run with Olivia Amato-af25d72ea4c0400daeac2707fc30994f.tcx"
        assert garmin_activity_type == "Running"
        assert os.path.exists(os.path.join(output_directory, filename))
예제 #13
0
    def test_cycling_smoketest(self):
        # Setup
        workout_data = self.loadTestData("peloton_workout_cycling.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_cycling.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_cycling.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "30 min Holiday Ride with Denis Morton"
        assert filename == "1607634579-30 min Holiday Ride with Denis Morton-d49cc8314b4e4f7ca1726394a90f6757.tcx"
        assert garmin_activity_type == "indoor_cycling"
        assert os.path.exists(os.path.join(output_directory, filename))

        tcx = self.loadOutputTCX(os.path.join(output_directory, filename))
        TCX.assertTcxSportMatches("Biking", tcx)
        TCX.assertTcxIdMatches(workout_data, tcx)

        TCX.assertTcxLapStartTimeMatches(workout_data, tcx)
        TCX.assertTcxTotalTimeSecondsMatches(workout_data, tcx)
        TCX.assertTcxTriggerMethodMatches(workout_summary, tcx)
        TCX.assertTcxIntensityMatches(workout_summary, tcx)

        TCX.assertTcxTotalPowerMatches(workout_summary, tcx)
        TCX.assertTcxMaximumSpeedMatches(workout_samples, tcx)
        TCX.assertTcxCaloriesMatches(workout_summary, tcx)

        TCX.assertTcxAvgHeartRateMatches(workout_summary, tcx)
        TCX.assertTcxMaxHeartRateMatches(workout_summary, tcx)

        TCX.assertTcxMaxBikeCadenceMatches(workout_summary, tcx)
        TCX.assertTcxAvgBikeCadenceMatches(workout_summary, tcx)

        TCX.assertTcxAvgWattsMatches(workout_summary, tcx)
        TCX.assertTcxMaxWattsMatches(workout_summary, tcx)

        TCX.assertTcxAvgResistanceMatches(workout_summary, tcx)
        TCX.assertTcxMaxResistanceMatches(workout_summary, tcx)
예제 #14
0
    def test_cycling_freestyle_smoketest(self):
        # Setup
        workout_data = self.loadTestData(
            "peloton_workout_cycling_freestyle.json")
        workout_summary = self.loadTestData(
            "peloton_workoutsummary_cycling_freestyle.json")
        workout_samples = self.loadTestData(
            "peloton_workoutsamples_cycling_freestyle.json")
        output_directory = self.getOutputDir()

        # Act
        title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
            workout_data, workout_summary, workout_samples, output_directory)

        # Assert
        assert title == "27 sec Just Ride"
        assert filename == "1595374979-27 sec Just Ride-88963f6daf89445387da4ee2e26015f9.tcx"
        assert garmin_activity_type == "Biking"
        assert os.path.exists(os.path.join(output_directory, filename))
    def run(config):
        numActivities = config.numActivities
        logger = config.logger
        pelotonClient = pelotonApi.PelotonApi(config.peloton_email,
                                              config.peloton_password)
        database = TinyDB('database.json')
        garminUploadHistoryTable = database.table('garminUploadHistory')

        if config.uploadToGarmin:
            garminUploader = garminClient.GarminClient(config.garmin_email,
                                                       config.garmin_password)
        '''
        Split the main work loop into a two-step approach:
        1. Download the requested number of workouts from Peloton API and saving them to the working directory.
        2. Process all the files in the working directory.  This converts the file to the .TCX format and 
            optionally uploads them to Garmin, as before.
        This enables easier dev/test of the steps independently.  Specifically, by skipping the first step,
        previously saved workout files can be processed without re-downloading them from Peloton.
        '''
        if config.skip_download:
            logger.info("Skipping download of workouts from Peloton!")
            workouts = []
        else:
            if numActivities is None:
                numActivities = input(
                    "How many past activities do you want to grab?  ")
            logger.info("Get latest " + str(numActivities) + " workouts.")
            workouts = pelotonClient.getXWorkouts(numActivities)

        #
        #   Step 1:  Download requested number of workouts to the working_dir directory
        #
        for w in workouts:
            workoutId = w["id"]
            logger.info("Get workout: {}".format(str(workoutId)))

            if w["status"] != "COMPLETE":
                logger.info("Workout status: {} - skipping".format(
                    w["status"]))
                continue

            workout = pelotonClient.getWorkoutById(workoutId)

            # Print basic summary about the workout here, because if we filter out the activity type
            # we won't otherwise see the activity.
            descriptor = tcx_builder.GetWorkoutSummary(workout)
            logger.info(
                "Downloading {workoutId} : {title} ({type}) at {timestamp}".
                format(workoutId=workoutId,
                       title=descriptor['workout_title'],
                       type=descriptor['workout_type'],
                       timestamp=descriptor['workout_started']))

            # Skip the unwanted activities before downloading the rest of the data.
            if config.pelotonWorkoutTypes and not descriptor[
                    "workout_type"] in config.pelotonWorkoutTypes:
                logger.info("Workout type: {type} - skipping".format(
                    type=descriptor['workout_type']))
                continue

            logger.info("Get workout samples")
            workoutSamples = pelotonClient.getWorkoutSamplesById(workoutId)

            logger.info("Get workout summary")
            workoutSummary = pelotonClient.getWorkoutSummaryById(workoutId)

            try:
                filename = tcx_builder.getWorkoutFilename(workout, "json")
                PelotonToGarmin.exportPelotonWorkoutFile(
                    config.working_dir, filename, workout, workoutSamples,
                    workoutSummary)
            except Exception as e:
                logger.error(
                    "Failed to save workout {id} to working directory {dir} - Exception: {ex}"
                    .format(id=workoutId, ex=e, dir=config.working_dir))

        #
        #   Step 2:  Process all files found under working_dir directory
        #
        workoutFiles = PelotonToGarmin.getPelotonWorkoutFiles(
            config.working_dir)
        logger.info("Begin processing {count} workout files.".format(
            count=len(workoutFiles)))
        for workoutFile in workoutFiles:
            workout, workoutSamples, workoutSummary = PelotonToGarmin.importPelotonWorkoutFile(
                workoutFile)
            if not workout:
                continue
            workoutId = workout["id"]

            # Print basic summary about the workout here, because if we filter out the activity type
            # we won't otherwise see the activity.
            descriptor = tcx_builder.GetWorkoutSummary(workout)
            workoutType = descriptor["workout_type"]
            logger.info(
                "Processing {workoutId} : {title} ({type}) at {timestamp}".
                format(workoutId=workoutId,
                       title=descriptor['workout_title'],
                       type=descriptor['workout_type'],
                       timestamp=descriptor['workout_started']))

            if config.pelotonWorkoutTypes and not workoutType in config.pelotonWorkoutTypes:
                logger.info(
                    "Workout type: {type} - skipping".format(type=workoutType))
                continue

            try:
                title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
                    workout, workoutSummary, workoutSamples,
                    config.output_directory)
                logger.info("Wrote TCX file: " + filename)
            except Exception as e:
                logger.error(
                    "Failed to write TCX file for workout {} - Exception: {}".
                    format(workoutId, e))

            # After we are done with the file, optionally copy the file to the archive directory, and/or retain
            # a copy of the file in the working directory.  Otherwise, the working file is deleted (default behavior).
            if config.archive_files:
                archive_dir = config.archive_dir
                if config.archive_by_type:
                    archive_dir += "/" + workoutType
                if not os.path.exists(archive_dir):
                    os.makedirs(archive_dir)
                shutil.copy(workoutFile, archive_dir)
            if not config.retain_files:
                os.remove(workoutFile)

            if config.uploadToGarmin:
                try:
                    uploadItem = Query()
                    workoutAlreadyUploaded = garminUploadHistoryTable.contains(
                        uploadItem.workoutId == workoutId)
                    if workoutAlreadyUploaded:
                        logger.info(
                            "Workout already uploaded to garmin, skipping...")
                        continue

                    logger.info(
                        "Queuing activity for upload: {}".format(title))
                    fileToUpload = config.output_directory + "/" + filename
                    garminUploader.addActivity(fileToUpload,
                                               garmin_activity_type.lower(),
                                               title, workoutId)
                except Exception as e:
                    logger.error(
                        "Failed to queue activity for Garmin upload: {}".
                        format(e))

        if config.uploadToGarmin:
            try:
                logger.info("Uploading activities to Garmin...")
                garminUploader.uploadToGarmin(garminUploadHistoryTable)
            except Exception as e:
                database.close()
                logger.info(
                    "Failed to upload to Garmin. With error: {}".format(e))
                input("Press the <ENTER> key to quit...")
                raise e

        logger.info("Done!")
        logger.info(
            "Your Garmin TCX files can be found in the Output directory: " +
            config.output_directory)

        if config.pause_on_finish:
            input("Press the <ENTER> key to continue...")
예제 #16
0
logger.info("Get latest " + str(numActivities) + " workouts.")
workouts = api.getXWorkouts(numActivities)

for w in workouts:
    workoutId = w["id"]
    logger.info("Get workout: " + str(workoutId))

    workout = api.getWorkoutById(workoutId)

    logger.info("Get workout samples")
    workoutSamples = api.getWorkoutSamplesById(workoutId)

    logger.info("Get workout summary")
    workoutSummary = api.getWorkoutSummaryById(workoutId)

    logger.info("Writing TCX file")
    try:
        tcx_builder.workoutSamplesToTCX(workout, workoutSummary,
                                        workoutSamples, output_directory)
    except Exception as e:
        logger.error(
            "Failed to write TCX file for workout {} - Exception: {}".format(
                workoutId, e))

logger.info("Done!")
logger.info("Your Garmin TCX files can be found in the Output directory: " +
            output_directory)

if pause_on_finish == "true":
    input("Press the <ENTER> key to continue...")
예제 #17
0
    def run(config):
        numActivities = config.numActivities
        logger = config.logger
        pelotonClient = pelotonApi.PelotonApi(config.peloton_email,
                                              config.peloton_password)
        database = TinyDB('database.json')
        garminUploadHistoryTable = database.table('garminUploadHistory')

        if numActivities is None:
            numActivities = input(
                "How many past activities do you want to grab?  ")

        logger.info("Get latest " + str(numActivities) + " workouts.")
        workouts = pelotonClient.getXWorkouts(numActivities)

        if config.uploadToGarmin:
            garminUploader = garminClient.GarminClient(config.garmin_email,
                                                       config.garmin_password)

        for w in workouts:
            workoutId = w["id"]
            logger.info("Get workout: {}".format(str(workoutId)))

            if w["status"] != "COMPLETE":
                logger.info("Workout status: {} - skipping".format(
                    w["status"]))
                continue

            workout = pelotonClient.getWorkoutById(workoutId)

            # Print basic summary about the workout here, because if we filter out the activity type
            # we won't otherwise see the activity.
            workoutSummary = tcx_builder.GetWorkoutSummary(workout)
            logger.info("{workoutId} : {title} ({type}) at {timestamp}".format(
                workoutId=workoutId,
                title=workoutSummary['workout_title'],
                type=workoutSummary['workout_type'],
                timestamp=workoutSummary['workout_started']))

            # Skip the unwanted activities before downloading the rest of the data.
            if config.pelotonWorkoutTypes and not workoutSummary[
                    "workout_type"] in config.pelotonWorkoutTypes:
                logger.info("Workout type: {type} - skipping".format(
                    type=workoutSummary['workout_type']))
                continue

            logger.info("Get workout samples")
            workoutSamples = pelotonClient.getWorkoutSamplesById(workoutId)

            logger.info("Get workout summary")
            workoutSummary = pelotonClient.getWorkoutSummaryById(workoutId)

            try:
                title, filename, garmin_activity_type = tcx_builder.workoutSamplesToTCX(
                    workout, workoutSummary, workoutSamples,
                    config.output_directory)
                logger.info("Writing TCX file: " + filename)
            except Exception as e:
                logger.error(
                    "Failed to write TCX file for workout {} - Exception: {}".
                    format(workoutId, e))

            if config.uploadToGarmin:
                try:
                    uploadItem = Query()
                    workoutAlreadyUploaded = garminUploadHistoryTable.contains(
                        uploadItem.workoutId == workoutId)
                    if workoutAlreadyUploaded:
                        logger.info(
                            "Workout already uploaded to garmin, skipping...")
                        continue

                    logger.info(
                        "Queuing activity for upload: {}".format(title))
                    fileToUpload = config.output_directory + "/" + filename
                    garminUploader.addActivity(fileToUpload,
                                               garmin_activity_type.lower(),
                                               title, workoutId)
                except Exception as e:
                    logger.error(
                        "Failed to queue activity for Garmin upload: {}".
                        format(e))

        if config.uploadToGarmin:
            try:
                logger.info("Uploading activities to Garmin...")
                garminUploader.uploadToGarmin(garminUploadHistoryTable)
            except Exception as e:
                database.close()
                logger.info(
                    "Failed to upload to Garmin. With error: {}".format(e))
                input("Press the <ENTER> key to quit...")
                raise e

        logger.info("Done!")
        logger.info(
            "Your Garmin TCX files can be found in the Output directory: " +
            config.output_directory)

        if config.pause_on_finish:
            input("Press the <ENTER> key to continue...")