Tuesday, December 22, 2015

Happy Holidays!



Merry FishMoose!

(See, because it's a fish bottle, with a moose candle...  Never mind.  Whatever you celebrate, enjoy the holidays.)

Physical Controls for the Digital Dash, Part 3

After careful thought and consideration (Yes, I'm serious.) I've decided to retire my gamepad side-arm controller in favor of my original scheme of using a Flic to control app access on the Digital Dash.  There are a couple of reasons for that:

1) The Flic is simply more reliable and easier to use.  It doesn't require recharging, connects automatically, and handles it's sleep mode more elegantly.  It also responds more quickly than the gamepad.

2) Many of the functions that the gamepad controls are either no longer necessary or are otherwise handled.  I don't need to download A-GPS data since I'm using the "Device Only" mode for GPS and I've brought the external temperature reading to the main screen, eliminating the need to pull up the Weather Channel app just to get that information.  And, of course, by installing a Flic dedicated to music control, I no longer need those functions on the gamepad.

3)  Finally, on our last few drives I kept closer track of just exactly how I was interacting with the system.  By far, the thing I did most often was to switch over to Google Maps to see the next turn information.  And that didn't happen very often.  I used to switch over more often to see the ETA information, but since bringing that to the main screen as well, it's available without any interaction.  The second most common thing was to check MyRadar to see incoming weather, but again, that was relatively rare.  Other things, such as switching music sources or setting a navigation destination simply didn't happen during the drive; I tended to do that at the beginning of a trip and never needed to change it en-route.

Taking all that into account, I decided to set up a second "App Control" Flic with the following functions.

When the main screen is showing:

  • Short Click - Launch Google Maps
  • Long Click - Launch MyRadar
  • Double Click - Launch GasBuddy

When on any screen EXCEPT the main screen:

  • Short Click - Return to the main screen

When on the Google Maps screen:

  • Long Click - Toggle Voice Navigation Guidance on or off

That seems like a pretty short list, but it represents all the things I'm likely to do while driving.  Of course, if I need to I can map a few other functions to the button, either by manipulating profiles (adding a triple click, for example) or by taking more contexts into account (such as a double click launching the navigation panel only when the Maps screen is showing).  I also have three other Flics that I could dedicate to controlling certain subsystems.

Time will tell what, if any, changes need to be made.



Wednesday, December 09, 2015

Schrödinger's Profile

How do you define when a Tasker profile is active?

One way, is to say it's active when all of its contexts are true.  In practice, though, that can sometimes be difficult to monitor directly, so we tend to use another method.  Commonly, we assume a profile is active when it runs its Entry task.

Normally, these two metrics align exactly and can be considered equivalent.  However, there are some profiles where that's not true; where the contexts are active, but the Entry task hasn't been run.

Since, depending on which definition we use, the profile can be considered both active and inactive, we call these Schrödinger's profiles.  (Yeah, okay.  Fine.  I'm the only one that calls them that, but I like it, and it's my blog.)

So what makes a profile behave like that, and what is it good for?

Creating a Schrödinger's profile is very easy; all you need to do is go into the profile properties and configure the Cooldown time.  Cooldown is a little-used parameter in Tasker that keeps a profile from running it's entry task until the the Cooldown time has elapsed.  If you set a Cooldown of 20 seconds, the profile can't activate any more often than that, even if all the explicit contexts for it are true.

One thing this type of profile is good for is ignoring some triggers, while allowing others of the same type to be acted on.

For example, in the Digital Dash project, I have a profile that watches for changes in the Google Maps navigation notification so that I can display ETA information on the main screen.
(As described here: http://mikesgeneralblog.blogspot.com/2015/10/navigation-eta-information-revisited.html.)

That notification can update many times a minute, particularly when there are a lot of navigation events happening close together, and when it starts counting down distance in tenths of a mile.  I'm not displaying the navigation instructions at all, and I don't really need second-by-second updates, so I've added a 30-second Cooldown to the profile that monitors the notification.  That way I still get data with the granularity I need, but don't waste a lot a system resources processing useless information; I get updates every 30 seconds even though the notification itself updates much more often than that.

The other thing you can do with a Schrödinger's profile is use it to replace a looping task.

I've never been conceptually happy with the Time and Torque task in the system.  I've previously described it as a "rogue task" because it's the only one that isn't triggered directly by some action. (http://mikesgeneralblog.blogspot.com/2015/06/digital-dash-documentation-part-9.html)  Instead, it gets kicked off by the Digital Dash startup task and simply loops about every 30 seconds until the system kills it via the shutdown task.  And that's always bothered me.  I'd prefer that it not run constantly in the background, and a profile with a Cooldown allows me trigger it to run regularly and on-demand without a loop.

Let's take a look at how to get that set up.  Let's say that, for some ungodly reason, you want Tasker to beep at you every five seconds.  We can make that happen.

The first thing to do is base a profile on a context that is always true.  For example, set up a global variable and Set it to something; doesn't matter what it is.  Then, you use a context of "Variable IS Set" in your profile.

Here's what that might look like (Assuming you've Set the %MyLoop variable elsewhere.)

Profile: Looper (468)
        Cooldown: 5
        State: Variable Value [ %MyLoop Set ]
Enter: Action (466)
        A1: Beep [ Frequency:8000 Duration:1000 Amplitude:12 Stream:3 ]


Enter this into Tasker and back all the way out.  After five seconds, you'll get a beep.  And after another five seconds you'll get...nothing.  And every five seconds after that, you'll get nothing.  You get one beep, and that's it.  Clearly, this isn't working.

That's because the Cooldown is really just a timer.  It gets triggered when the profile becomes active and starts counting down.  Once it reaches the end, the profile is allowed to run its Entry task.  The problem is, Cooldown doesn't automatically reset itself.  It only starts when the profile becomes active, and since, in the example above, the profile never becomes inactive, the Cooldown timer won't fire again.

So, we need to make the profile go inactive and then activate it again so the timer can restart itself.

We can easily add a line to the Entry task to accomplish the first part:

Profile: Looper (468)
        Cooldown: 5
        State: Variable Value [ %MyLoop Set ]
Enter: Action (466)
        A1: Variable Clear [ Name:%MyLoop Pattern Matching:Off ]
        A2: Beep [ Frequency:8000 Duration:1000 Amplitude:12 Stream:3 ]



By clearing the %MyLoop variable, we've made the profile go inactive because its context is no longer true.  Of course, we're still not going to get repeating beeps, because all we've done at this point is turn off the profile.  Now we need to activate it again.  We can do that by adding an Exit task.

Profile: Looper (468)
        Cooldown: 5
        State: Variable Value [ %MyLoop Set ]
Enter: Action (466)
        A1: Variable Clear [ Name:%MyLoop Pattern Matching:Off ]
        A2: Beep [ Frequency:8000 Duration:1000 Amplitude:12 Stream:3 ]

Exit: Reaction (467)
        A1: Variable Set [ Name:%MyLoop To:True Do Maths:Off Append:Off ]



So, what happens is, when the profile runs its Entry task (after the Cooldown period has expired) it gets turned off by line A1 in the Entry Task.  This causes it to immediately run its Exit task, which resets the %MyLoop variable, making the context True again, and restarting the Cooldown period.  Note that deactivating the profile does not stop the entry task from running to completion, so we get our beep.  And every five seconds after that, we'll get another beep until we go into Tasker and either disable the profile with its On/Off switch or explicitly clear the %MyLoop variable on the Var panel.

This is the technique I used to convert the Time and Torque loop to a triggered task rather than a loop, and it's working quite well.  I still get regular updates, but nothing is sitting in a Wait state.  And I'm happier with that.