Logging driving time with Tasker, Toggl and a bluetooth radio

As a dedicated follower of the Church of Cortex, I have been getting into the idea of time tracking. I track my weight and exercise, and tracking how I spend my life seems like a good logical next step. The idea being to figure out how much time I spend doing any given thing, and then reviewing the data will make it easier to improve my life.

One thing I wanted to track is time I spend driving around in my car. I’ve been driving more recently, and I want to know how much so I can plan what my next vehicle will be. Long story short, I’ve figured out a way, and below are the boring technical details.

My desired result was to log the amount of time I spend driving into time tracking service Toggl, as I’m already using that for a few other things and if I can get 100% of my time tracked in one app then so much the better. So I needed to figure out how to do that automatically.

My first thought was that my phone could log this; it connects to my car stereo via bluetooth every time the engine starts. That’s my data input. I couldn’t rely on automation stalwart IFTTT, partly because they don’t support Toggl integration at the moment, and partly because I’ve found their bluetooth and wifi triggers to be fairly unreliable. Nor could I rely on premium automation alternative Zapier, because there’s no way to trigger anything based on a bluetooth connection in Zapier.

Next up was Tasker, an Android automation app that I’ve had for donkeys years. It’s not pretty, and it’s more complicated than I’d like, but it gets things done. Even Tasker didn’t have a Toggl integration, but it does have enough flexibility that I could make use of Toggl’s API. Fortunately, someone else has already done a lot of the dirty work; HHrebus on GitHub has built tasker-toggl, a complete interpretation of Toggl’s API in files you can import into Tasker. I wasn’t able to get his code to work myself, but I learned enough in the process to assemble the below guide.

So, with no further ado: how to start and end a Toggl timer with a tasker profile.

Before you start with any of the complicated bits, you need to prep Toggl to receive your timers. You need your API token, which you can get by clicking your name in the bottom left corner of the web app, then scrolling to the bottom of the Profile Settings menu. Also, you need to link your timers to either a Workspace, a Project, or a Task. The guide below is for a Project, because that makes the most sense here, but you should be able to figure out how to change my steps if you’d rather link to one of the others. I’ve set up a Project called “Driving”. Once you’ve set up your project, you need to get the Project ID number, which annoyingly you cannot get from Toggl’s web UI. So it’s time to make first use of that API token and do the following to firstly get the list of Workspaces, then get the list of Projects associated with that workspace.

curl -v -u 1971800d4d82861d8f2c1651fea4d212:api_token \ #put your api key in here
	-X GET https://www.toggl.com/api/v8/workspaces  #this gets a list of your workspaces

curl -v -u 1971800d4d82861d8f2c1651fea4d212:api_token \ #put your api key in here too
	-X GET https://www.toggl.com/api/v8/workspaces/777/projects #put your project ID here

The second command will list all Projects in that workspace. Copy the ID of the Project you want your timers to track to somewhere safe. I’d recommend saving your Toggl API token into a Tasker global variable, that way you can use it in other places without having to type it out repeatedly. To see your Tasker global variables, hit the menu icon on the top right and then Preferences, and untick “Beginner Mode” in the UI tab. You’ll now see “VARS” as an option next to Profiles, Tasks and Scenes. Go to the VARS tab, hit plus and add a variable called %TOGGL_TOKEN. Press the blank space to the right of your variable and enter your API token.

The only other bit of prep to do is to install RESTask from the Play Store. This is a Tasker plugin that makes interfacing with REST APIs like Toggl’s easier to deal with. Now you’re ready to create your Tasker Tasks.

Originally I tried using the “Start a Time Entry” and “Stop a Time Entry” functions, but this early version often didn’t connect as my phone was dropping out of a wifi network as I drove away. So when my phone connects at the start, I’m only going to log the time to a variable. Then, when the phone disconnects, I log the full time entry in one easily repeatable request.

So my first task, Toggl-driveStart, is a single step; a JavaScriptlet (Plus sign > Code > JavaScriptlet) with the following code:

var d = new Date();
setGlobal("DRIVE_START_STRING", d.toISOString());

All the rest of the settings I left as default. It’s such a basic script that if it comes across any errors then I have more serious problems than the script. All it does is get the current date and time, and saves it, as a text string in the ISO 8601 date format, to a Tasker global variable until we need it when the drive ends.

My second task, Toggl-driveStop, is where the business gets done. The first action is another JavaScriptlet as follows:

var drive_stop_date = new Date();
var drive_stop_string = drive_stop_date.toISOString();
var drive_start_date = new Date(global('DRIVE_START_STRING'));
var_drive_len = (drive_stop_date - drive_start_date) / 1000;
var request_body = '{"time_entry":{"description":"Driving","duration":';
request_body += drive_len;
request_body += ',"start":"';
request_body += global('DRIVE_START_STRING');
request_body += ',"stop":"';
request_body += drive_stop_string;
request_body += '","pid":123456789l,"created_with":"tasker"}}';

To break down the first four lines:

  1. Get the drive stop date and time
  2. Convert the drive stop datetime to the same ISO 8601 format as before
  3. Retrieve the drive start ISO datetime from the global variable and convert it back into a date
  4. Get the duration of the drive in seconds by taking the stop date away from the start date. Then dividing by 1000 because that duration defaults to milliseconds.

I need both dates as ISO strings because Toggl uses those as Start and Stop times. I needed the dates as JavaScript dates to get the duration, which Toggl also requires. Note that Duration doesn’t need to match the exact time between the start and stop time. All the lines after that are building up the request_body variable which is what we’re going to send off to Toggl. Make sure you enter your Project ID after “pid”.

The second action is then a RESTask REST call (Plus sign > Plugin > RESTask). You need to set up the RESTask as follows:


Settings tab

Request Type: Post

Host: https://www.toggl.com/api/v8/time_entries

Basic Auth Username: %TOGGL_TOKEN

Basic Auth Password: api_token

Timeout: 120

Enable custom body: ticked

Custom Body: %request_body

Headers tab

Add one header

Name: Content-Type

Value: application/json

Leave the rest as default, then hit save. The only other things to do in the RESTask are to increase the “Timeout (Seconds)” to 120 to match the above, and to tick “Continue Task After Error”. This allows us to plan for a failed connection and keep retrying until it works.

Action 3 is an If (Plus > Task > If”). The condition you want is %rtcode (the RESTask HTTP status code output variable) Doesn’t Equal (NEQ) 200. Basically, if the RESTask isn’t successful.

Action 4 is a Wait (Plus > Task > Wait). I’ve set mine to 3 minutes, but if you’re concerned about constant retries draining your battery you can set this higher.

Action 5 is a Goto (Plus > Task > Goto). The Type is “Action Number”, and you’re pointing it at Action #2, our RESTask.

Action 6 is an End If (Plus > Task > End If).

Action 7 is a Variable Clear (Plus > Variables > Variable Clear) clearing %DRIVE_START_STRING to make sure we don’t end up with some weird situation where your drive start time gets stuck.

That brings us to the end of the tasks. Then you just need to associate them with a profile. Go to the profiles tab, hit plus, and if you’re copying my method of using a BlueTooth connection, then choose State > Net > BT Connected as your trigger. Make sure you put your stereo’s BT name in the Name box, otherwise this will be triggered by every BlueTooth connection. Add Toggl-driveStart as your first task. Then press and hold on Toggl-driveStart until a menu appears letting you Add Exit Task. Hit that and choose your Toggl-driveStop task.

And there you have it. A Tasker task for logging driving stats. it’s not 100% accurate – the BlueTooth stereo takes a good minute or two to get connected to my phone after the engine starts. But it gets pretty close!

Update 05/10/2018

I’ve had a few issues since setting this up with some tracked times not appearing, and others being duplicated. I massively increased the timeouts, and these issues disappeared. I’ve updated the instructions above to reflect this.