I have a couple of interesting reviews coming up for headphones. Each product design has something special and unique about it, but they all share a common function: being powered by a battery. If only there was a way of testing the battery life in a neat way.
Oh wait, I already had done this once, it’s time for a re-make, but what’s more important, it’s time to share all the things I learned while re-working years old project.
The old Tasker project I used to test the battery life was very simple. Press a button to start a timer, play a very long playlist on a loop (wrap a Bluetooth speaker in a towel and take it outside) and log a disconnect time, as this presumably would be the time when the battery dies. I even had profiles estimating battery life based on current consumption!
Working with Bluetooth devices is easier now. Thanks to improvements in Android and Bluetooth stack, connected devices return the battery levels back to your phone. You can check them at glance in the Bluetooth menu of your phone. It’s enough for the average user, but not good enough for me. I needed more.
In my efforts to extract precious usage data, I came up with a Tasker profile that runs an automatic test and logs the battery levels every minute. Progress can be traced in a notification, the data set can be exported as a REST request and I used AutoTools to plot a handy graph of each test. These always look fancy in any reviews. They tell readers, that I know what I’m doing!
I’m not going to blame you for being completely disinterested in this project. After all, it’s a tool for me to generate some review data and later on use that data to create another project covering the Postgres database in NodeRED. That’s a subject for another time. What’s really interesting about this project is the whole “making of” which should give you some insight into how to make your projects even better.
New things I learned in Tasker
It’s been a while since I had to create something in Tasker. I had a great time trying to troubleshoot each step of what seemed to be a dead easy concept in my head. As with all concepts, things get much more complex in practice. If this is the first time you hear about Tasker and want to know more about how to use this Android automation tool, I have a great startup guide already and more basic tips and tricks.
Here is what I learned this time:
It’s a great practice to store your network-related data in variables. Instead of hardcoding every REST request, you can build one from variables on the spot. You can take this to the next level by introducing dynamic switching (based on your location/WiFi) or even creating toggles to easily send your data to a testing server instead.
This simple profile sets my DDNS/REST URL and toggles the testing environment so I don’t submit messy data to my main automation server. Should anything change (like my DDNS provider/credentials etc) I only have to update these in a single task rather than looking for all instances with hardcoded entries.
Don’t be afraid of having highly focused tasks that are called to the main thread with Perform Task action. It’s a great way to save yourself time and add logical structure to your project. These act as “functions” in traditional programming languages – a piece of easy-to-maintain, reusable code called on request.
A great example of this task is one that updates my notification. I could call Autonotification action each time I want to update the information but if something goes wrong or I want to change how the notification looks, I have to edit each instance of the action. Calling the “Update Notification” task and passing necessary variables (if you don’t store them as global variables) is a better option.
Your instinct may tell you to keep the number of Tasks to the minimum, which each one neatly containing each action for your project, but you are doing yourself a disservice. It may look to the untrained eye messier to have a long Task list in your Tasker Project, but Tasker doesn’t care about that.
The introduction of TaskerNet increased the importance of the setup task – a task that runs once on import. It’s a great way to gather all the data needed to set the Tasker task correctly. Even if you don’t plan on sharing your creations with anyone, having a good setup task streamlines the backup/restore process.
My task allows me to set up a URL path to send the data, and enter server credentials and other settings. It’s called from the main thread through Perform Task action, therefore it can be part of your “Run this task on import”. Adding a simple
%Setup = true/false the condition also allows these to be part of your main task, but only appear once on the first run.
In my Tasker Tips & Tricks article, I outlined a nice way to label your Projects, Profiles, Tasks, Actions and variables. I enhanced this a little. From my guide, your variable should start with a two-letter abbreviation (or more) taken from the Project Name. It makes searching for project-relevant variables so much easier. There is a bonus for adding “s” to all project variables containing setup data.
#sample project variable %BT_starttime //saved start time of the task in Bluetooth Test project %BTs_path //setting variable, intended to be more persistent
Why? If you ever need to reset your task, you can do this with Variable Clear with pattern matching.
%BT_* will clear all project variables at once leaving project settings variables intact. This leads me to my next point:
Keep Arrays in order!
I also learned how to order data in arrays without reshuffling it. Array Push action will let you select the index value but if you want the values to be in a reversed order (like I needed it for my graphs) there is a neat trick I found on r/Tasker.
A12: Variable Set [ Name: %last_element To: %BT_BatteryArray(#<)+1 Max Rounding Digits: 3 Structure Output (JSON, etc): On ] A13: Array Push [ Variable Array: %BT_BatteryArray Position: %last_element Value: %bt_battery_level ]
The main difference between (#<) and (#) is in how elements are counted. Here is a short explainer:
array = [apple, banana, null, null, orange, null] (#) = 3 elements (counts actual elements) (#<) = 6 elements (coutns indexes of the array)
If you push your element with (#) as the index, you will end up with the data stored in the middle of the sample array (before orange) while (#<) will place it at the end (after orange).
Don’t be afraid to look at your old projects in Tasker and rework them using your latest knowledge about the app. It’s satisfying to see these projects expand and get even better over time. You’ll likely encounter things that can be done better, or simply bugs you haven’t come across before.
Thanks to this Project I also found out that one of my past write-ups about converting time to readable format had a pretty serious flaw. I wasn’t getting expected label names at the exact minute mark, and it took me a moment to realise why.
d = ("0"+Math.floor(par/86400)).slice(-2); h = ("0"+Math.floor((par%86400)/3600)).slice(-2); m = ("0"+Math.floor((par%3600)/60)).slice(-2); s = ("0"+par%60).slice(-2); var timer = ""; timer += (par>86400?d+"d ":""); timer += (par>3600?h+"h ":""); timer += (par>60?m+"m ":""); timer += s+"s"; vs (fixed) d = ("0"+Math.floor(par/86400)).slice(-2); h = ("0"+Math.floor((par%86400)/3600)).slice(-2); m = ("0"+Math.floor((par%3600)/60)).slice(-2); s = ("0"+par%60).slice(-2); var timer = ""; timer += (par>=86400?d+"d ":""); timer += (par>=3600?h+"h ":""); timer += (par>=60?m+"m ":""); timer += s+"s";
I’ve updated the article since but if it wasn’t for this project, the code would contain the bug for a long time.
If you haven’t looked at your Tasker projects for a while, perhaps this article will give you the motivation to give them a glance over and see how else you could improve them. I hope you’ll find my new tips useful. For anyone with great little hacks and tips for how to improve projects in Tasker feels free to share them in this Reddit thread. I’m always on the lookout for more.