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'));
http.send();
return(http.responseText);
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:
Similarly, to query HabitRPG, I'm using:
function query_task()
var http = new XMLHttpRequest();
http.open("GET",http_get_url,false);
http.setRequestHeader("x-api-user", global('HabitrpgUserid'));
http.setRequestHeader("x-api-key", global('HabitrpgApiToken'));
http.send();
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.
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.