Giter Club home page Giter Club logo

garmin-csv-plan's Introduction

Garmin Plan

Actions Status

This is a PHP implementation of the great program that mgifos created here. The intentions of the program is to parse a CSV file and create workouts in Garmin Connect. It has the ability to:

  • Import workouts from a file into Garmin Connect
  • Prefix workouts with some text Ex.: Convert 14k, 4x 1.6k @TMP TO HANSON:14k, 4x 1.6k @TMP
  • Add notes to workout steps Ex.: run: 225:00; Example notes here. ("Example notes here." will be inserted as a note to the workout step.)
  • Schedule existing workouts based upon name: Ex.: Simple Google Sheets CSV Plan
  • Delete workouts that are made based upon the CSV file
  • ONLY delete workouts (Do not import anything)
  • Schedule workouts on Garmin Connect calendar based upon a start OR end date
  • Create swimming workouts by specifying the pool size as an option Ex.: --pool-size=25yds
  • Import AND schedule multiple workouts per day Ex.: multi-events-day.csv
  • Nest repeated steps Ex.: test-repeater.csv

Google Sheet Examples

Example of all Workout Types

Simple Google Sheets CSV Plan

Ultra 80K Plan

Example

CONVERT THIS -

running: 2x4x2'@z5
- warmup: 20:00
- repeat: 2
   - repeat: 4
      - run: 1:00 @z5
      - recover: 2:00 @z2
   - recover: 4:00
- cooldown: 10:00

INTO

Garmin Workout

AND SCHEDULED ONTO

Garmin Calendar

THROUGH THIS COMMAND -

docker-compose exec garmin-dev bin/console garmin:workout tests/Resource/all-example.csv schedule -s '2021-05-01' -r 'TriPrep: '

Setting up the application to develop or run

  1. Download and install PHP and composer
  2. Run composer install
  3. Put your username and password in .env file
  4. Run the application by ./bin/console garmin:workout

Running the program through Docker

  1. Copy the CSV file to the root directory (The file will then be copied to the Docker container)
  2. docker-compose run garmin ./bin/console garmin:workout <file.csv>

Usage

Specify a CSV file to create and delete workouts in Garmin connect and schedule them on the Garmin calendar.

Examples

You can remove the -m and -p flag by copying .env to .env.local AND updating the file with your username and password under GARMIN_USERNAME and GARMIN_PASSWORD.

GARMIN_AUTHENTICATION_FILE_PATH in the .env.local file can be used to change the default path for the garmin_credentials.json. By default it is routed to the default Symfony project directory.

If you have pool workouts included in your plan, then you must specify the --pool-size option with the length of the pool. Ex.: 25yds 100m

# Basic example of importing workouts into Garmin
bin/console garmin:workout <file.csv> -m <garmin_email> -p <garmin_password>

# Import AND Schedule workouts into Garmin on January 1, 2020. End date is assumed based upon plan length.
# End date can be specified with the -d flag. The same can be assumed with the start date.
bin/console garmin:workout <file.csv> schedule -m <garmin_email> -p <garmin_password> -s '2020-01-01'

# Same as above but delete all previous items first, import items and schedule them, and prefix with HANSON: before all workouts
bin/console garmin:workout <file.csv> schedule -m <garmin_email> -p <garmin_password> -s '2020-01-01' -x -r 'HANSON:'

# Only delete the previous workouts (notice capital "x")
bin/console garmin:workout <file.csv> schedule -m <garmin_email> -p <garmin_password> -s '2020-01-01' -X -r 'HANSON:'

# Do a mock run of importing workouts like above
bin/console garmin:workout <file.csv> schedule -m <garmin_email> -p <garmin_password> -s '2020-01-01' --dry-run

Arguments

Value Description
<path-to-file.csv> The RELATIVE CSV file path that you want to import into Garmin connect
import OR schedule Specify import OR schedule to either just import the workouts into Garmin connect or import AND schedule the workouts. [default value: "import"]

Options

Short form Long form Description
-m --email=EMAIL Email to login to Garmin [default: ""]
-p --password=PASSWORD Password to login to Garmin [default: ""]
-x --delete Delete previous workouts from CSV file
-X --delete-only NLY delete workouts that are contained in the CSV file
--dry-run Dry run that will prevent anything from being created or deleted from Garmin
--pool-size The pool size specified for all workouts in the plan Ex.: 25yds OR 100m
-r --prefix=PREFIX A prefix to put before every workout name/title
-s --start=START Date of the FIRST day of the first week of the plan Ex.: 2021-01-01 YYYY-MM-DD
-d --end=END Date of the LAST day of the last week of the plan Ex.: 2021-01-31 YYYY-MM-DD
-h --help Display help message
-q --quiet Do not output any message
-V --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n --no-interaction Do not ask any interactive question
-e --env=ENV The Environment name. [default: "dev"]
--no-debug Switches off debug mode.
-v OR -vv OR -vvv --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Developing and running the program through Docker

  1. Start by building and running the docker file - docker-compose up garmin-dev

  2. Install dependencies - docker-compose exec garmin-dev composer install

    a) Adding dependencies or removing dependencies can be done through docker-compose exec garmin-dev composer require <package>

    b) Updating dependencies csn be done through docker-compose exec garmin-dev composer update

  3. Run the docker install by running docker-compose up garmin-dev (This runs the docker container and keeps it up)

  4. Execute a command by running docker-compose exec garmin-dev bin/console garmin:workout ...

Running PHPUnit tests

If you want to run PHPUnit tests, then you can easily run it through the dev build.

  1. Follow the above to develop and run the program through Docker.
  2. Run the following - docker-compose exec garmin-dev vendor/bin/phpunit

Overriding Docker

Create a new file in the root called docker-compose.override.yaml.

version: '3.3'

services:
  garmin-dev:
    environment:
      XDEBUG_CONFIG: "client_host=<local_IP>"

Debugging the application through PhpStorm

  1. If running linux, then you will need to modify the docker-compose.yaml file and add your IP in place of host.docker.internal

  2. Go to PhpStorm -> Settings -> Languages & Frameworks -> PHP -> Servers

    a) Click "+"

    b) Name docker-cli (Same as serverName under PHP_IDE_CONFIG environment variable)

    c) Host _

    d) Default 80

    e) Debugger Xdebug

    f) Check the checkbox next to "Use path mappings"

    g) Modify the absolute path on the server to /var/www/html

garmin-csv-plan's People

Contributors

pygoubet avatar raistlfiren avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

garmin-csv-plan's Issues

Not able to add workout to calendar

When I try to load a workout, all goes well up to a successful upload of the workouts.
The next step fails with:
2023-04-30T22:39:32+02:00 [info] Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated.

Any ideas on how to resolve this issue?

Running on linux with PHP 8.1.2.

Authentication failed

Hi,

It does always abort with an error that the authentication failed.

In GarminConnect.php line 158:

  Authentication failed - please check your credentials (<html lang="en-US" class="no-js" xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta charset="utf-8" />
    <title>Garmin: Maintenance</title>

...

The credentials are correct, I tried on the garmin web page to verify.

Any hints?

Regards,
Florian

PHP 8 support

Hello! Please could garmin-csv-plan be updated to run on PHP 8?

I'm on the current LTS version of Ubuntu and composer install gives:
Root composer.json requires php ^7.2.5 but your php version (8.1.2) does not satisfy that requirement.

Simply editing composer.json to allow PHP 8 doesn't seem to be enough, because I then get:

[Symfony\Component\DependencyInjection\Exception\RuntimeException] Cannot autowire service "App\Command\WorkoutCommand": argument "$name" of method "__construct()" is type-hinte d "string", you should configure its value explicitly.

Thanks in anticipation
Paul

Support multiple sessions per day

Hi,
The feature introduced in PR #6 has stopped working.
Could you consider re-adding the ability to encode several workouts on the same day?

Workouts fail to create

v.05 in docker on MacOs 14.4.1
When importing or scheduling workouts, in the "Creating workouts" phase, each workout fails with " * Workout - [x] failed to create".
Same issue in prod and dev. Unfortunately I do not have a php debugging environment set up to investigate more deeply. I suspect more info about the cause could be found in the response from this

maz@Mathieus-Air garmin-csv-plan-0.5 % docker-compose run garmin ./bin/console garmin:workout pfitz.csv import -m [email protected] -p FTcGZdgZr6C26qy -r 'Pfitz: ' -n -x -vvv    

Starting workout import/export command
======================================

Validating and accessing - pfitz.csv
------------------------------------

                                                                                                                        
 [OK] File valid                                                                                                        
                                                                                                                        

Parsing Workouts
----------------

 * 14k, 6k @ LT
 * 18k long run
 * 8k recovery
 * 14k easy
 * 24k long run
 * 14k, 10 strides
 * 25k, 13k @ mp
 * 21k long run
 * 23k long run
 * 28k long run
 * 14k, 8k @ LT
 * 29k, 16k @ mp
 * 13k, 3x1600 intervals
 * 16k, 8k @ LT
 * 11k, 10 strides
 * 34k long run
 * 16k double
 * 17k, 9k @ LT
 * 10k recovery
 * 11k, 6 strides
 * 25k, 19k @ mp
 * 14k, 6x800 intervals
 * 19k, 11k @ LT
 * 14k, 5x600 intervals
 * 10k tune-up race
 * 30k, 22k @ mp
 * 18k, 5x1200 intervals
 * 11k, 8 strides
 * 8k, 6 strides
 * 6k recovery
 * 11k, 3k @ mp

[info] Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated
Deleting old workouts
---------------------



Creating workouts
-----------------

 * Workout - 14k, 6k @ LT failed to create
 * Workout - 18k long run failed to create
 * Workout - 8k recovery failed to create
 * Workout - 14k easy failed to create
 * Workout - 24k long run failed to create
 * Workout - 14k, 10 strides failed to create
 * Workout - 25k, 13k @ mp failed to create
 * Workout - 21k long run failed to create
 * Workout - 23k long run failed to create
 * Workout - 28k long run failed to create
 * Workout - 14k, 8k @ LT failed to create
 * Workout - 29k, 16k @ mp failed to create
 * Workout - 13k, 3x1600 intervals failed to create
 * Workout - 16k, 8k @ LT failed to create
 * Workout - 11k, 10 strides failed to create
 * Workout - 34k long run failed to create
 * Workout - 16k double failed to create
 * Workout - 17k, 9k @ LT failed to create
 * Workout - 10k recovery failed to create
 * Workout - 11k, 6 strides failed to create
 * Workout - 25k, 19k @ mp failed to create
 * Workout - 14k, 6x800 intervals failed to create
 * Workout - 19k, 11k @ LT failed to create
 * Workout - 14k, 5x600 intervals failed to create
 * Workout - 10k tune-up race failed to create
 * Workout - 30k, 22k @ mp failed to create
 * Workout - 18k, 5x1200 intervals failed to create
 * Workout - 11k, 8 strides failed to create
 * Workout - 8k, 6 strides failed to create
 * Workout - 6k recovery failed to create
 * Workout - 11k, 3k @ mp failed to create

                                                                                                                        
 [OK] Workout import was successful.                                                                                    
                                                                                                                        

AbstractStep::setGarminID() must be of the type int or null

Hi @Raistlfiren,

The last version of garmin-csv-plan does not run on my raspbian.
Could you help me?
Thanks advance,

  • install and run steps:
git clone https://github.com/Raistlfiren/garmin-csv-plan.git
cd garmin-csv-plan 
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
./composer.phar install
# credential in .env.local file
./bin/console garmin:workout tests/Resource/all-example.csv -n
  • Result:
Starting workout import/export command
======================================

Validating and accessing - tests/Resource/all-example.csv
---------------------------------------------------------

                                                                                                                        
 [OK] File valid                                                                                                        
                                                                                                                        

Parsing Workouts
----------------

 * Lift Weights
 * 12 @ 400m with 400m rest
 * 1000 yards
 * 20 miles
 * Casual swim
 * 30 Mile Ride
 * 2x4x2'@z5

Creating workouts
-----------------

[error] Error thrown while running command "garmin:workout 'tests/Resource/all-example.csv' -n". Message: "Argument 1 passed to App\Library\Parser\Model\Step\AbstractStep::setGarminID() must be of the type int or null, float given, called in /home/pi/garmin-csv-plan/src/Service/GarminHelper.php on line 73"

[critical] Uncaught Error: Argument 1 passed to App\Library\Parser\Model\Step\AbstractStep::setGarminID() must be of the type int or null, float given, called in /home/pi/garmin-csv-plan/src/Service/GarminHelper.php on line 73


In AbstractStep.php line 153:
                                                                                                                                                                         
  Argument 1 passed to App\Library\Parser\Model\Step\AbstractStep::setGarminID() must be of the type int or null, float given, called in /home/pi/garmin-csv-plan/src/S  
  ervice/GarminHelper.php on line 73                                                                                                                                     
                                                                                                                                                                         

garmin:workout [-m|--email EMAIL] [-p|--password PASSWORD] [-x|--delete] [-X|--delete-only] [--dry-run] [-r|--prefix [PREFIX]] [-s|--start START] [-d|--end END] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-e|--env ENV] [--no-debug] [--] <command> <csv> [<type>]

GarminHelper.php -- Undefined property: stdClass::$workoutId when using CSV from tests folder

When testing the syntax/functionality of this package using the csv file in the tests folder here: https://github.com/Raistlfiren/garmin-csv-plan/blob/master/tests/Resource/multi-events-day.csv, the following error occurred:

Command: bin/console garmin:workout multi-events-day.csv import

Output:

Starting workout import/export command
======================================

Validating and accessing - multi-events-day.csv
-----------------------------------------------

                                                                                                                        
 [OK] File valid                                                                                                        
                                                                                                                        

Parsing Workouts
----------------

 * 10x30''30''
 * easy cycle
 * easy run
 * long run

 Does the following look correct? (yes/no) [yes]:
 > yes

Creating workouts
-----------------

[critical] Error thrown while running command "garmin:workout 'multi-events-day.csv' import". Message: "Warning: Undefined property: stdClass::$workoutId"

In GarminHelper.php line 69:
                                                     
  Warning: Undefined property: stdClass::$workoutId  
                                                     
                                                     

Software / system versions:
OS: MacOS 13.6.3

php --version

PHP 8.3.7 (cli) (built: May  7 2024 16:35:26) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.7, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.7, Copyright (c), by Zend Technologies

If rolling back to an older PHP version would fix the issue, happy to do that to use this amazing package!

Empty weeks ignored

When planning I want to leave some weeks empty.
Like:

WEEK,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
1,,,,"running: W4 - Recovery Run (3.8k)
- run: 3800m @ z2
- cooldown: lap-button",,"running: W4 - Long Run (5k)
- run: 5000m @ z2
- cooldown: lap-button",
2,,,,,,,
3,,,,,,,
4,,"running: W5 - Short Intervals (6.5k)
- warmup: lap-button
- repeat: 8
  - run: 400m @ 4:10-3:50
  - recover: 1:30 @ z2
- cooldown: lap-button",,"running: W5 - Recovery Run (6.5k)
- run: 6500m @ z2
- cooldown: lap-button",,"running: W5 - Long Run (7.2k)
- run: 7200m @ z2
- cooldown: lap-button",

Then I schedule this plan and define a starting date (-s). The empty weeks (2 und 3) are ignored, means week 4 is scheduled directly after week 1.

Would be great if this is possible.

Parser.php does not recognize repeating runs

Hello
as can be seen in ultra-80k....csv test file, we could define a run and then reuse by just entering the name of it. However, in this case it fails with

In Parser.php line 98:
Call to a member function getName() on null

Found that this is because we always try to build a new workout (line 189) based on type that is not repeated in case of same exercise....we need to create a "memory"
thanks :)

repeat in repeat support

Hi,

It would be great to support repetition in a repetition.
e.g.

running: 2x4x2'@z5
- warmup: 20:00
- repeat: 2
  - repeat: 4
    - run: 1:00 @z5
    - recover: 2:00 @z2
  - recover: 4:00
- cooldown: 10:00

Currently,

I have tried unsuccessfully to program the feature. I get lost in the recursion (repeat in repeat and so on) and json serialization.
I will nevertheless propose a PR which ease the workout parsing by treating it as a Yaml string. Maybe you could consider it if you would like to add the feature.

An unexpected response code was found: 400

Hi there, I am getting this error while trying to schedule a workout, It works on a dry-run but not on a real run. Any help would be appreciated and many thanks for this app!

Creating workouts

[error] Error thrown while running command "garmin:workout 'tests/Resource/Bike_workouts.csv' schedule --start=2021-12-06 -vvv". Message: "An unexpected response code was found: 400"

[debug] Command "garmin:workout 'tests/Resource/Bike_workouts.csv' schedule --start=2021-12-06 -vvv" exited with code "1"

In GarminConnect.php line 296:

[dawguk\GarminConnect\exceptions\UnexpectedResponseCodeException]
An unexpected response code was found: 400

Exception trace:
at /var/www/html/vendor/dawguk/php-garmin-connect/src/dawguk/GarminConnect.php:296
dawguk\GarminConnect->createWorkout() at /var/www/html/src/Service/GarminHelper.php:68
App\Service\GarminHelper->createWorkouts() at /var/www/html/src/Library/Handler/AbstractHandler.php:137
App\Library\Handler\AbstractHandler->createGarminWorkouts() at /var/www/html/src/Library/Handler/AbstractHandler.php:88
App\Library\Handler\AbstractHandler->handle() at /var/www/html/src/Library/Handler/ScheduleHandler.php:13
App\Library\Handler\ScheduleHandler->handle() at /var/www/html/src/Library/Handler/HandlerFactory.php:25
App\Library\Handler\HandlerFactory->buildCommand() at /var/www/html/src/Command/WorkoutCommand.php:89
App\Command\WorkoutCommand->execute() at /var/www/html/vendor/symfony/console/Command/Command.php:255
Symfony\Component\Console\Command\Command->run() at /var/www/html/vendor/symfony/console/Application.php:929
Symfony\Component\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:96
Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /var/www/html/vendor/symfony/console/Application.php:264
Symfony\Component\Console\Application->doRun() at /var/www/html/vendor/symfony/framework-bundle/Console/Application.php:82
Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /var/www/html/vendor/symfony/console/Application.php:140
Symfony\Component\Console\Application->run() at /var/www/html/bin/console:42

ERROR: Service 'garmin-dev' failed to build

Hi @Raistlfiren,

Following issue #17 I have tried to run the code using a container.
It does not work neither.

$ docker-compose up garmin-dev
Building garmin-dev
Step 1/4 : FROM php:7.4-cli-alpine
 ---> 91cefd5154f6
Step 2/4 : RUN apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS   && pecl install xdebug   && docker-php-ext-enable xdebug   && apk del .phpize-deps
 ---> Running in eaae4e5fa364
ERROR: Service 'garmin-dev' failed to build: The command '/bin/sh -c apk add --no-cache --virtual .phpize-deps $PHPIZE_DEPS   && pecl install xdebug   && docker-php-ext-enable xdebug   && apk del .phpize-deps' returned a non-zero code: 139

Any idea?

Command line -m & -p ignored

Hi,
-m and -p (also --email and --password) seem to be ignored (can be checked by adding
echo ('trying to log using - '. $garminUsername.' / '.$garminPassword);
in Client.php line 11 (john/doe are logged out)

I could not find quickly where the command line parameters are taken into account.
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.