Diary of a geek

August 2014
Mon Tue Wed Thu Fri Sat Sun

Andrew Pollock


Other people's blogs


RSS feed

Contact me

JavaScript required

Tuesday, 05 August 2014

Lifehacking with NFC, Tasker and HabitRPG

Oh man, I'm such a geek...

Being a single parent has required a considerable amount of self-discipline on my behalf. I find I do best in an environment with routine to make sure stuff gets done. One of the things I did to try and make sure stuff got done was to form positive habits. To help and make this a bit more "fun", I started using HabitRPG, an online role-playing game based on habits.

I've only ever used it in a half-arsed manner, and as a result, I die a lot. Often I'll do my dailies, but then forget to mark them off. Sometimes I just fall off the habit wagon altogether. And die.

One of my dailies is to scoop my cat's litterboxes. For whatever reason, I find this a tad onerous, and had found myself falling out of the habit of doing it on a daily basis. My cat deserves better than this, so I wanted to get back on the habit wagon, but make it a bit more "fun" as well.

I love NFC, I've been a big NFC weenie for a long time. It's a solution looking for a problem. I have a huge collection of NFC tags, and I've finally found a problem I could use them with. I wanted to make it more frictionless to mark a task as completed in HabitRPG. I didn't want to have to take out my phone, unlock it, open the HabitRPG app and check off the daily task. I just wanted to wave my phone at an NFC tag. Here's how I did it.

The inimitable Paul Fenwick, who first inspired me to use HabitRPG, has a way more complicated set up to achieve something similar. The Site Reliability Engineer in me wanted the least number of moving parts and third-parties to have to get from my phone to HabitRPG.

After some hunting around, I found this wiki page on integrating Tasker with HabitRPG's API, so based on that breadcrumb, I got hacking.

I'd not used Tasker before. I was already using AutomateIt to do some other, reasonably dumb automation on my phone, though. Tasker is a little bit obtuse, and it took me a couple of days of casual fiddling with it to wrap my head around it's usage model. The fact that it can run arbitrary JavaScript, and that NFC Tools integrates with it is where the real awesome lies.

So based off the wiki, I crafted a couple of bits of JavaScript, one to mark daily tasks as complete on HabitRPG, and one to query HabitRPG to see if they have been marked as complete.

For the former, it was trivial, using NFC Tools, to write an NFC tag that then runs the Tasker task to call the HabitRPG API to mark a daily task as complete. That goal was now complete.

The equally satisfying part was also having Tasker do a time-based conditional nag based on the state of the daily task in HabitRPG. So now if it gets to 4:45pm and I haven't scooped the litterboxes, my phone literally tells me I'd better go do it.

I've also done the same thing with putting the dishwasher on. I've stuck an NFC tag on the dishwashing powder bottle lid, and I get a conditional reminder before bed time. It used to be an unconditional reminder with AutomateIt, and it was dumb, because I rarely forget to put the dishwasher on. Now, I can use HabitRPG to keep state on it instead.

The hunk of JavaScript to update HabitRPG is very simple:

function mark_completed() { 
  var http = new XMLHttpRequest();
  http.open("POST", http_post_url, false);
  http.setRequestHeader("x-api-user", global('HabitrpgUserid'));
  http.setRequestHeader("x-api-key", global('HabitrpgApiToken'));

try { 
  var result = mark_completed(); 
} catch(e) { 
  var error = e.message; 

All of the interesting stuff is defined in variables preceding the JavaScript in the task definition. Here's a screenshot of the Task in Tasker that tells a thousand words:

Screenshot of Tasker task that uses HabitRPG API to mark a
task complete

Similarly, to query HabitRPG, I'm using:

function query_task() { 
  var http = new XMLHttpRequest();
  http.setRequestHeader("x-api-user", global('HabitrpgUserid'));
  http.setRequestHeader("x-api-key", global('HabitrpgApiToken'));
  var p = JSON.parse(http.responseText);
  return p['completed'];

try { 
  var task_completed = query_task(); 
} catch(e) { 
  var error = e.message; 

It's only slightly trickier because you have to parse the JSON blob that comes back.

Again, a screenshot.

Screenshot of Tasker task that
uses HabitRPG API to query task state

Now maybe I'll stop dying so much in HabitRPG, my cat will have the clean toilet she deserves, and I'll stop getting reminded about putting the dishwasher on when I already have. Better living through automation, that's my motto.

[14:39] [geek] [permalink]

Day 188: Sickness, Thermomix consultancy, some tennis

Today derailed a bit. Sarah sent me a message saying that she thought Zoe was too sick to go to Kindergarten, so I picked her up and brought her home.

I had a 9am coffee lined up with the Thermomix Group Leader for my area to talk about becoming a Thermomix consultant, so Anshu offered to stay and keep an eye on Zoe for me, which made going to that still a possibility.

The chat ended up going a lot longer than I expected, so Anshu hung around for lunch with us after I got back, and then left. I decided to just do the house cleaning today instead of tomorrow, and Zoe mostly just followed me around and helped and generally entertained herself.

She indicated to me that she'd still like to go to her tennis class, so we were getting ready for that when I got a text message from Megan's Mum about picking up Megan. We'd miscommunicated, and I hadn't realised I was picking her up, so it worked out well that we were still going to go for tennis.

So we drove to Kindergarten, collected Megan, and both girls went to tennis class. I used the time to give my accountant a call, and about half way through the class Zoe seemed to have had enough and sat it out.

After Megan finished, we drove home again and the girls played dress ups and generally entertained themselves, which was good, because I think I've contracted whatever illness Zoe currently has and am not feeling particularly perky.

Jason arrived to pick up Megan, and Sarah arrived shortly after, and I pretty much collapsed on the couch. I've decided that as much as I'd like to go to yoga class tonight, I'm going to give it a miss and go to bed early instead.

[02:33] [life] [permalink]