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:

Configuration:

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.

Yet More Dell Docking

Dell’s dock didn’t work. The Belkin USB 3.0 hub did. For a while, at least. After a few months of fairly solid performance driving the 2x LG 34UC97 ultrawide monitors using 2x Plugable USB3.0 DP adapters, problems started to appear. One monitor wouldn’t come on.  Or the other wouldn’t come on. Or they’d flicker wildly when actual work was being done. The bosses declared them “unusable” and worked from a meeting room, rather than stare at the pile of failing technology in front of them. Shame upon my family name!

It looks like the issue is the Belkin dock, rather than the Plugable adapters. While these docks are happily pushing twin 1080p monitors elsewhere in the business, it seems that pushing two lots of 3440×1440 monitors is too much for the chipset. I’ve kept them, and at some point I’ll test them out to see if they’re properly wrecked or whether they can enjoy an easy retirement pushing the same twin 1080p as their comrades.

So it was back to online shopping, trying to find something that would do the job. I have to say, the market for USB 3.x docks is moving at a serious pace now. It seems like none of the options I checked out in January were really available six months ago. In the end I settled for the Kensington SD4600P, a dock that advertises as supporting dual 4K, via one DP port and one HDMI port. They’ve been working for nearly two months now with fairly minimal issues; occasionally the XPS15 forgets which monitors go where, but that is quickly solved.

They seem fairly nice units, however there is one thing I will note. Of two installations on the same Dell XPS 15s, one was significantly easier than the other. The easy one was just checking that the video drivers were up to date, and we were away. The other struggled to drive both monitors at the same time until a firmware update was performed. And something in the firmware update had a terrible effect on the laptop’s onboard graphics. The lower half of the screen flickered and froze constantly after the firmware update (which should only have affected the dock!) and nothing I tried would fix it. Eventually the boss needed to go, so I shut it off. When it was turned on the next morning, it was fine. I have no idea what happened there. I had tried turning it off and on again, but it appears the extended power-down was the answer.

Opening .AJP CCTV Video Files

If you’re unlucky enough to find yourself needing to view CCTV in an .AJP file format, (as far as I can tell these are created by older Hangzhou Hikvision DVRs) then the following will hopefully be helpful.

Some Googling suggested an application called JPEG2000 AJP Video Player. Downloading it and installing it (always use a VM! Do not install random applications on a production machine! Eat your greens!), will lead to disappointment. Not just because it’s a hideous old application, but because it doesn’t work on modern Windows – I’ve tested on 32 and 64 bit versions of Windows 7 and no amount of futzing with Compatibility Mode settings will get it to run properly, and often not even install at all.

What you’ll need to do is set up a Windows XP virtual machine (SP3 worked fine for me) and install the JPEG2000 application there. Once installed (it atually calls itself JM Integrated Remote Station) you can view your AJP file with the “Player” section of the application.

The application is pretty user-unfriendly and some features still won’t work reliably (I couldn’t rewind the video without closing the application to start it again!), but there is a silver lining in that you can output the video to a standard AVI file that will play nicely elsewhere. You can only do it one camera at a time, in real time, but having seen other horrible vintage CCTV programs, any standard-ish export option is a good one.

Blogging

So yeah , I’m blogging again. I’m very web 2.0.

Goals for the blog this time are a bit more concrete: I’m an IT admin at a small to medium enterprise and from time to time I come across useful information, which I’ll be sharing here. There may also be occasional rambling. Anyway, on with the blog!