Showing posts with label BMW. Show all posts
Showing posts with label BMW. Show all posts

Tuesday, December 22, 2015

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.



Monday, August 17, 2015

More Tweaks and Tuning

Before and after our last roadtrip, I made a few changes to the Digital Dash system.  Nothing major, but I did address a few long-standing issues that have proven to be worth the effort to correct.

The first has to do with the Destinations panel.  If you've read some the previous entries, you know this is a pop-up panel that holds five preset destinations; all I have to do is pick one and the system starts navigating to it.

Normally it has an entry for Home, three places that we visit fairly often, and a slot for an ad hoc destination that's just called "Current".  Usually, I just edit the address for that last entry and don't bother changing the on-screen name.

However, for our last trip I needed to change everything except for the Home designation since we were going to be visiting several places in an unfamiliar area.  Changing the addresses was easy; all I needed to do was change the entry list in the "%V3_Destinations" variable.  However, to get the right names on the screen, I was going to have to manually edit the pop-up scene.  I wasn't too wild about doing that because I was just going to have to change it back after the trip and there's always the chance that I'd end up slightly moving the position of one of the elements.  And since the process that chooses the navigation destination relies on precise screen positioning, a small change would stop it from working.

So instead, I made a new variable in the Startup task: "%V3_DestinationNames" and turned it into an array.  It, of course, holds the onscreen names that I want to have displayed.  I also added a small loop in the Startup task that reads that array and uses Tasker's "Element Text" to change the names in the scene.  That way there's no risk of accidentally moving something and it makes future changes much easier to do.

I actually have two copies of both "%V3_Destinations" and "%V3_DestinationNames" in the Startup Task.  One holds my normal, default values and the other can be used for future trips.  I just disable the pair that I'm not using.

The second thing I did was go through and re-balance all the task priorities.  I admit I hadn't paid much attention to this before, even though I should have.  Before I did this, I would get occasions where the interface would be slow to respond; I'd hit the Next Track button and nothing would happen, so I'd hit it again and all of sudden it would jump two tracks.  Or it would take several seconds to pause the music.

To fix that, I went into every profile that dealt with user interaction and bumped the launched task priority up to around 40.  I also tweaked other tasks while I was at it, and the result is that the system is now very responsive to user input and there's never any confusion about whether the screen (or Bluetooth controller) tap has registered.

The last thing I did on the tablet was to fix an annoyance that has been around for quite some  time.  Every once in awhile the overlay scenes on Torque would "blink"; disappearing for a second before they would pop back on.  When this first started happening, long ago, I did a little investigation, but somehow came to the conclusion that it was something inherent in either Tasker or the Android OS.  After all, I was displaying four overlays, each with many elements and possible interactions and I figured I was just pushing the limits of the systems and it was something that I would have to live with.  And since was an annoyance rather than an actual problem, I just let it go.

But when I began to look at it a little deeper, I realized that it was actually my profile and task that was removing the displays.  I still don't really know why this is happening; the profile is triggered by Torque being in the foreground and none of my code is changing that condition when the problem manifests itself.  For some reason, Torque just loses focus for a fraction of a second from time to time, which was triggering the profile's exit task and removing the display, only to put it right back on again.

Fortunately, the fix was pretty simple.  I modified the exit task for the profile to start with a one-second Wait.  After that, it checks Tasker's built-in %PACTIVE variable to see if the profile is active.  If it is, the exit task is stopped.  This de-bouncing code is enough to stop the problem.  Since I put it in, the display has been rock-solid.

The final change I made was on the phone, rather than the tablet.  Again, if you read some of the earlier posts, you'll know that every couple of minutes the phone is supposed to read the temperature from its sensor and send it to the tablet via an AutoRemote message for display on the main screen.

The problem is that this has never worked quite right.  Messages wouldn't get sent consistently, or they'd get sent but never arrive, or a bunch of them would show up at once.  I ran lots of tests and tried lots of things, but I could never quite figure out the problem.

As it turns out, there were two issues:  One was that AutoRemote normally sends its messages through the web via Google.  That service seems to be a bit buggy and unreliable, causing lost and delayed messages.  The fix was to switch to using AutoRemote's Direct Messaging option.  Now, messages go from the phone to the tablet...uh, directly...using the Bluetooth tether between the two devices.

 That took care of messages the were sent but not received, but the system on the phone still wasn't sending messages consistently.  This time, the problem was of my own making.

When I decided to mount the phone in the car as well as the tablet, I did so because I wanted to have Waze constantly running and visible because I like its road hazard reporting.  However, I don't like its on-screen speedometer; it just too small to be useful.  So, I reused some code that I had originally developed to put a speedometer on Google Maps, without really paying much attention.

I had used a simple task that grabbed Tasker's %LOCSPD variable, converted it from meters-per-second to miles-per-hour and fed that to an onscreen variable.  The task would then wait before looping back and repeating.  The problem was that it was "waiting" exactly one millisecond.  My speed was being reported with great granularity, but that loop was blocking the low-level task I had set up to send the temperature messages.

Rather than rewrite this routine to use AutoLocation, I simply modified it by adding the temperature sending code to the loop.  Now, it has a loop counter that is incremented every time the speed is updated and after so many times, will send the temperature and reset the counter so it can start incrementing again.  I also changed the wait to 250 milliseconds, which is much more reasonable.  The result is that I now get consistent temperature updates about once per minute on the tablet.  It finally works the way I wanted.

None of these changes were very big, but they have made the system more stable, responsive, and user-friendly.

Thursday, August 06, 2015

Physical Controls for the Digital Dash



I know, of course, that it's somewhat dangerous (not to mention illegal in many places) to operate a touch screen device while driving.  That's why I've wanted to add physical controls to my system for quite a while.  In fact, the latest version of the system was built with that in mind, with a structure that was prepped for it.

I had initially become pretty excited about the Flic Bluetooth button when I heard about it last year on the Tasker Google Group.  I backed their project on Indiegogo and ended up ordering five of them.  I've become a bit disillusioned, though.  They were supposed to deliver in March, and it's now August and I still don't have them.

I had intended, originally, to mount four in the car: two on the center console for the passenger, and two on the back of the steering wheel (that mirrored the console buttons) for the driver.  I figured that with two buttons, I could control just about everything in my system.  I may still mount one on the console for passenger music control, but I've found something better for complete driver control.


This is a "Compact Bluetooth Gamepad" that I bought from GearBest.  It only costs about $7, has a rechargeable  battery, and incorporates nine buttons (including a four-way joystick) that send standard Android keycodes to your device.  And with Tasker and the AutoInput plugin, I can intercept those codes and make them do anything I want.  And what I want is to control the digital dash system...completely.

Here are the keycodes it sends in it's default mode.  There are at least two other modes that change the mapping, but I haven't messed with those.


I've remapped all the buttons except for the Play/Pause control; that one I use as is.  In addition, each of the joystick buttons uses two linked Tasker profiles to allow it to recognize two different types of activation: a short click, or a longer, held one. (I could do that with the buttons as well, but haven't needed to...yet.)



This picture shows how I've got it mounted in the car.  An inverted "U-shaped" piece of plastic with a couple of self-adhesive rubber feet to hold it in place and a couple of Velcro dots to hold the controller to it.  It gives me a very nice little sidearm controller that's easy to reach and use.  In the descriptions that follow, "up" is toward the front of the car.

Here's a list of functions that each button can perform, broken down by screen:

On the Main Screen

Joystick Up Click - Launch Google Maps
Joystick Up Held - Show the list of pre-programmed destinations
Joystick Down Click - Launch the MyRadar weather app
Joystick Down Held - Launch the Weather Channel app
Joystick Left Click - Replay previous song
Joystick Left Held - Show the list of favorite songs
Joystick Right Click - Skip to the next (random) song
Joystick Right Held - Launch PowerAmp if the music source variable is currently set to "Local".  If it's set to "Net", launch Pandora, instead
Volume Down Click - Launch Pandora and start playing my pre-existing 60's music station
Volume Up Click - Launch Pandora and start playing a mix of my pre-existing stations.
Back Key Click - Launch Pandora and start playing my pre-existing 70's Rock station
Enter Key Click - Launch GasBuddy

On Google Maps

Joystick Up Click - Return to Main Screen
Joystick Up Held - Toggle Voice Navigation on and off (uses AutoInput to press on-screen controls)
Joystick Down Click - Download A-GPS data using the GPSStatus app. (uses AutoInput to press on-screen controls.  Automatically returns to the main screen.)

On Radar or Weather Apps

Joystick Click Down - Return to Main Screen

On GasBuddy

Enter Key Click - Return to Main Screen

When the Destinations List is Showing

Joystick Down Click - Step the cursor down to highlight the next destination in the list.  If you try to step below the last one, it wraps around back to the top of the list.

Joystick Up Click - Step the cursor up to highlight the previous destination in the list.  If you try to step above the first one, it wraps around back to the bottom of the list.

Joystick Left Click - Cancel destination selection and remove the on-screen list

Joystick Right Click - Select a destination and send it to Google Maps.  Navigation starts automatically.

When the Favorite Songs List is Showing

Joystick Down Click - Step the cursor down to highlight the next song in the list.  If you try to step below the last one, it wraps around back to the top of the list.

Joystick Up Click - Step the cursor up to highlight the previous song in the list.  If you try to step above the first one, it wraps around back to the bottom of the list.

Joystick Left Click - Cancel song selection and remove the on-screen list

Joystick Right Click - Select a song and send it as a search to PowerAmp.  The song will start playing and then the system returns automatically to the main screen.

The Play/Pause key executes the Play/Pause function regardless of what screen is showing.

It seems a bit complicated when you're just reading through the list, but the operation is really pretty intuitive (at least to me.)  That's the beauty of designing your own system; you can have something that makes perfect sense to you, even if others don't see it the same way.

If you've read some of my previous entries, you might notice that there are a few functions that aren't accounted for.  They're used so rarely that I didn't feel it was necessary to add those in, but if I get bored, or ambitious I might do it anyway.  The missing functions are: launch ScannerRadio, set the PowerAmp EQ, toggle Auto-Brightness, and launch the fireplace app.

 I just got back from a long weekend mini-vacation where we put about 700 miles on the car and the system worked very well.  So far, I'm very pleased with how this part of the project has turned out.

Friday, June 19, 2015

Digital Dash Documentation, Part 9: Reading Time and Torque Data

This is a bit of a "rogue" task.  Where the other tasks in the system are triggered by some sort of external stimuli (e.g. a button is tapped, a new song comes on, app focus changes) this one is kicked off by the startup sequence, goes off into its own little world, and is killed when the system shuts down.  It spends most of its time sleeping, only to wake up every 25 seconds or so to see what's going on.  Its purpose is to update the time display on the main screen and let me know when it's time to start thinking about getting gas.


V3_TimeAndTorque (336)
A1: Variable Set [ Name:%mytime To:%TIME Do Maths:Off Append:Off ] 
A2: Variable Split [ Name:%mytime Splitter:. Delete Base:Off ] 
A3: Variable Set [ Name:%mytime1 To:%mytime1-12 Do Maths:On Append:Off ] If [ %mytime1 > 12 ]
A4: Variable Set [ Name:%mytime To:%mytime1:%mytime2 Do Maths:Off Append:Off ] 
A5: Variable Set [ Name:%V3_DispTime To:%mytime Do Maths:Off Append:Off ] 

It would have been much easier to just link Tasker's built in %TIME variable to an on-screen display but, unfortunately, it only reports out in 24-hour time; and I wanted a 12-hour display, so I need to manipulate the data a bit.  

It's pretty straight forward: The %TIME variable is copied into a local variable (%mytime) and split into variables holding the hour (%mytime1) and the minutes (%mytime2).  We then subtract 12 from the hour, but only if it's greater than 12.  So, for example, 10 is left alone but 15 has 12 subtracted from it to yield 3.

We then concatenate the hours, a ":", and the minutes back into the %mytime variable and set the global variable %DispTime equal to it.  %DispTime, of course, is the source for a text element on the main display.

The Z3's analog gas gauge has the disturbing habit of going along saying, "Yup, Everything's fine; plenty of gas.  No problem here, Chief.  We can go a long way yet".  Until it gets down to about a third of a tank.  Then it starts sucking it down like a thirsty drunk on Dollar Pitcher Night.  That's one reason there are three displays dealing with gas mileage on the main screen.  The following part of the task is designed to wake me up if I'm not paying attention and let me know that it's time to start looking for some 91-octane go-juice.

A6: Run Shell [ Command:/data/data/burrows.apps.busybox/app_busybox/tail -1 /storage/emulated/0/torqueLogs/trackLog.csv Timeout (Seconds):0 Use Root:Off Store Output In:%obd_log Store Errors In: Store Result In: Continue Task After Error:On ] 

Every five seconds Torque adds a new line to its log file with several pieces of information, including the "Estimated Distance To Empty" (EDE) that it calculates using the current MPG and the vehicle profile I set up.  Since I only want to know the latest information, I use the "tail" command, which simply reads in the last line of the file (tracklog.csv) and stores it in a local variable (%obd_log).

A7: Variable Split [ Name:%obd_log Splitter:, Delete Base:Off ] 

I then split the base variable so that I can access the one piece of data that I really want.

A8: Test Element [ Scene Name:V3_LH Element:LowFuel Test:Element Visibility Store Result In:%lowdistanceindicator Continue Task After Error:On ] 

The line above tests the LowFuel element on the V3_LH scene to see if it is visible or not and stores the result in %lowdistanceindicator.

A9: If [ %obd_log6 < 60 & %lowdistanceindicator ~ false ]

The next thing we do is test to see if the indicator is still invisible and the EDE (stored in the 6th position of the data array) has fallen below my set point; in this case, 60 miles.

A10: Element Visibility [ Scene Name:V3_LH Element Match:LowFuel Set:True Animation Time (MS):0 ] 

If both of those conditions are true, we make the LowFuel element (a translucent red square) be visible over the Distance To Empty element on the screen.

A11: Say [ Text:Warning. Range limit is under sixty miles. Engine:Voice:default:default Stream:3 Pitch:5 Speed:4 Respect Audio Focus:On Network:Off Continue Task Immediately:Off Continue Task After Error:On ] 
A12: End If 

We also give a verbal warning before ending the test started back in line 9.  The reason for doing it this way is that I want a verbal warning when low range point is first reached, but after that I only want the indicator to stay lit.  Once the conditions in the test have been met for the first time, the second part of the test will fail since the indicator is already on; so no repeated verbal warnings.  If I just tested the EDE, the system would be yelling at me about every 30 seconds.

A13: If [ %obd_log6 > 60 & %lowdistanceindicator ~ true ]
A14: Element Visibility [ Scene Name:V3_LH Element Match:LowFuel Set:False Animation Time (MS):0 ] 
A15: End If 

This routine clears the visual indicator when the EDE rises above 60 again.  That is, when I fill up and tell Torque that I have plenty of gas again.

A16: Wait [ MS:0 Seconds:25 Minutes:0 Hours:0 Days:0 ] 
A17: Goto [ Type:Action Number Number:1 Label: ] 

The task finishes by going back to sleep again.  When it wakes up, it starts all over at line one.  Doing it this way means that the clock isn't accurate to the second, but it's close enough for what I want.

Digital Dash Documentation, Part 8: Torque Overlay Handling

This is the last profile (at least on the tablet) that I need to describe.  This one simply handles showing the four main overlay scenes when Torque is in the foreground, and removing them when it loses focus.

Profile: V3_TorqueOverlay (342)
Application: Torque
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_ShowMainOverlay (340)

A very simple profile.  Whenever we are in the system (i.e. %V3_DrivingMode is SET) and Torque comes to the foreground, we show the four overlay screens.  When Torque loses focus (i.e. we switch to another app) the scenes are hidden. 

A1: Show Scene [ Name:V3_TopMain Display As:Overlay, Blocking Horizontal Position:100 Vertical Position:0 Animation:System Show Exit Button:Off Continue Task Immediately:On ]
A2: Show Scene [ Name:V3_LH Display As:Overlay, Blocking Horizontal Position:4 Vertical Position:196 Animation:System Show Exit Button:Off Continue Task Immediately:On ]
A3: Show Scene [ Name:V3_Bottom Display As:Overlay, Blocking Horizontal Position:100 Vertical Position:200 Animation:System Show Exit Button:Off Continue Task Immediately:On ]
A4: Show Scene [ Name:V3_RH Display As:Overlay, Blocking Horizontal Position:200 Vertical Position:200 Animation:System Show Exit Button:Off Continue Task Immediately:On ]

The entry task just shows the previously created scenes.  All of them are blocking overlays because they all contain elements that the user can interact with.

Exit: V3_HideMainOverlay (341)
A1: Hide Scene [ Name:V3_TopMain Animation:None Continue Task After Error:On ]
A2: Hide Scene [ Name:V3_TopSources Animation:None Continue Task After Error:On ]
A3: Hide Scene [ Name:V3_TopEQ Animation:None Continue Task After Error:On ]
A4: Hide Scene [ Name:V3_CancelOverlays Animation:None Continue Task After Error:On ]
A5: Hide Scene [ Name:V3_LH Animation:None Continue Task After Error:On ]
A6: Hide Scene [ Name:V3_Bottom Animation:None Continue Task After Error:On ]
A7: Hide Scene [ Name:V3_FavoriteSongs Animation:None Continue Task After Error:On ]
A8: Hide Scene [ Name:V3_Destinations Animation:None Continue Task After Error:On ]
A9: Hide Scene [ Name:V3_RH Animation:None Continue Task After Error:On ] 

For the exit task, I took what my father would call the "brute force and awkwardness" approach.  That is, I don't check to see what scenes might be showing and selectively hide them; instead, I just hide any scene that could possibly be showing.  The "Continue Task After Error" lets that happen.

Digital Dash Documentation, Part 7: Incoming Phone Commands

When the digital dash system starts up, it makes a Bluetooth tethering connection to my phone.  There is a Tasker profile on the phone that listens for this connection to be made, and when it sees it, it runs a startup task of its own.  The details of that will be covered in a later part of the documentation, but the only thing we're interested in now is the fact that part of that sequence launches a low-priority looping task that repeats about every three minutes.

What that task does is to read the current ambient temperature from the phone's sensor (via Tasker's built-in %TEMP variable) convert it to Fahrenheit, append the degree symbol, and send it off to the tablet via an AutoRemote message.


Profile: V3_IncomingCommands (368)
State: AutoRemote [ Configuration:All Messages ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_HandlePhoneCommands (369)

This profile, running on the tablet, simply listens for any incoming AutoRemote message.  When it sees one, it fires off it's entry task.  Since I'm really only sending one message, I'm not making use of any of AutoRemote's filtering capabilities; I just look for any message and let the entry task figure out what to do with it.

A1: Variable Set [ Name:%V3_CurrentTemp To:%arpar() Do Maths:Off Append:Off ] If [ %arcomm ~ Temp ]

When it comes in, the AutoRemote message looks like this: "the temperature"=:=Temp (Where "the temperature" is the current ambient temperature, including the degree symbol.)  In AutoRemote terms, anything to the left of the =:=  is called the parameter(s) and is contained in the %arpar() local variable.  LIkewise, anything to the right of the symbol string is called the command and is found in the %arcomm local variable.  All this task does is check to make sure that this is a "TEMP" command and, if it is, sets the %V3_CurrentTemp global variable equal to the parameter payload.  %V3_CurrentTemp is used as the source for the temperature text element on the V3_RH scene shown on the main display. 

Although I'm only sending one type of message at this time, the system is easily expandable if I want to add additional types.

Digital Dash Documentation, Part 6: Compass

A very simple profile and task this time.  This is the routine that updates the compass on the main display and the compass and speed on the Google Maps overlay.


Profile: V3_Compass (326)
State: AutoLocation Location [ Configuration:Location Report Name: V3_Compass ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_Compass (327)

Back in the system startup task, we initialized an AutoLocation routine that began tracking GPS data and gave it the instance name of "V3_Compass".  This profile watches for any updates in the data from that instance and fires off its entry task when something changes.

A1: Variable Set [ Name:%index To:((floor((%albearing+11.25)/22.5))%16+16)%16+1 Do Maths:On Append:Off ] 

The above line converts the bearing information into an index variable in the range of 1 to 16 with 1 representing North and 16 being all the way around the compass ring at NNW.

A2: Variable Set [ Name:%V3_Heading To:%V3_Compass(%index) Do Maths:Off Append:Off ] 

This line just applies the index of the %V3_Compass array that holds the list of possible directions and sets the %V3_Heading value with it.  That variable is used as the source for a text element on both the V3_RH and V3_MapSpeedometer scenes.

A3: Variable Set [ Name:%V3_Sprnd To:round((%alspeed*2.236936290544)*10)/10 Do Maths:On Append:Off ] 

This line converts the speed returned by AutoLocation into miles per hour (rounded to the nearest tenth) and sets %V3_Sprnd equal to it.  That variable is used as a source on the V3_MapSpeedomter screen.  The primary speed display on the main screen does not use this value since Torque is able to read GPS data on its own and put it into a gauge display.

Thursday, June 18, 2015

Digital Dash - Some Visual Changes

Among the many things that I'm not, one is a graphic designer.  But even I can tell when something needs a bit of improvement.  When I first started this project I was more concerned about functionality than appearance, and even when I tried to take a stab at that, the results were...adequate (at best).

So, I've made a few changes that, I think, improve the look of the system.  You can see the results, below.  But even if these aren't dramatic improvements, they have the happy coincidence of reducing the number of external graphics used.  Now, there are only four:  the display background used for the readouts on the right side of the screen, the low mileage indicator (which is really just a red-tinted version of the display background), and the two vehicle logos.  Everything else has been replaced with native Tasker elements.  If I get ambitious (or bored) I may try to cut that down even further.

The screenshots, below, show the system connected to the Jag, with the snarling cat logo, which I haven't shown before.



This is the main screen.  The connection indicators, which had formerly been non-descript yellow dots, have been replaced with standard icons that better represent what each connection does.  I also made the track and artist information white.  It had been yellow before, which I had hoped would add a little color to the screen, but just ended up hampering readability and looking a little out of place.



The audio sources sub-panel is now cleaner, with text buttons and simple bars dividing them.



Likewise, the EQ sub-panel has been been given a simplifying makeover.  The "PowerAmp EQ" on the left is just a label.  At this point I don't see a real need to be able access the full EQ settings from here, but if I change my mind it'll be easy to make it a live button and add another dividing bar to the left.

Not huge changes, but I think they're an improvement,  And certainly easier to manage.

Wednesday, June 17, 2015

Digital Dash Documentation, Part 5: Music Info

One of the functions the digital dash project is to provide an continual display of the currently playing music track and artist.  Since there are two possible sources for music (Pandora and PowerAmp) we need routines to extract that information from either app.

Profile: V3_GetPandoraInfo (281)
Event: AutoNotification Intercept [ Configuration:Event Behaviour: true
Notification Type: Only Created Notifications
Notification Apps: Pandora
Get All Fields : true ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_PandoraInfo (347)

Whenever Pandora starts playing a new track, it adds a entry to the tablet's notification panel (after first destroying the previous one) that contains the name of the track and the artist.  I use AutoNotification to monitor for the creation of that entry.

A1: Variable Set [ Name:%V3_Track To:%antitle Do Maths:Off Append:Off ]
A2: Variable Set [ Name:%V3_Artist To:%antext Do Maths:Off Append:Off ]

The Pandora information comes into Tasker as the local variables %antitle, and %antext.  I simply copy those values to global variables that are used as the sources for text elements on the V3_TopMain scene.

Getting information from PowerAmp is a little more involved and uses an intent that PowerAmp fires off any time it starts playing a new track.

Profile: V3_GetPowerAmpInfo (345)
Event: Intent Received [ Action:com.maxmpz.audioplayer.TRACK_CHANGED Cat:None Cat:None Scheme:* Mime Type:* ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_PowerAmpInfo (346)

The profile is configured to listen for this specific intent.

A1: Variable Split [ Name:%track Splitter:, Delete Base:Off ] 

The intent payload from PowerAmp contains 18 pieces of information concatenated into a comma-separated bundle that comes into Tasker as the local variable "%track".  For my application, most of that information isn't needed, but I still need to split the variable in order to get at the information I do want. 

A2: Variable Set [ Name:%artist To:%track1 Do Maths:Off Append:Off ] 
A3: Variable Split [ Name:%artist Splitter:= Delete Base:Off ] 
A4: Variable Set [ Name:%V3_Artist To:%artist2 Do Maths:Off Append:Off ] 

After the initial split, the array variable %track1 contains the bundle start designation as well as the first piece of information I want. For example, it might look like this: Bundle[{artist=Queen.  So, I copy that to a temporary local variable (%artist) and split that, this time using an = as the Splitter. What remains in %artist2 after the split is the artist name, in this case, Queen.  That then gets copied into the global variable %V3_Artist, which is referenced as a source for one of the elements in the V3_TopMain scene (to be described later).

A5: Variable Set [ Name:%song To:%track14 Do Maths:Off Append:Off ]
A6: Variable Split [ Name:%song Splitter:= Delete Base:Off ]
A7: Variable Set [ Name:%V3_Track To:%song2 Do Maths:Off Append:Off ] 

I perform a similar set of splits with the 14th entry in the %track variable array. This contains something like this: title=Bohemian Rhapsody.  I copy that to the local %song variable, split it with an = and copy the resulting %song2 value to %V3_Track, which is, again, linked to a text element on the main screen.

Digital Dash Documentation, Part 4: Tablet Power Status

This is a pair of very simple profiles that handle updating the main screen element that shows the tablet's current power status.  In addition to displaying the remaining battery percentage, it also shows whether or not the tablet is plugged in by underlining the battery value when it detects a external power connection

Profile: V3_TabletPluggedIn (337)
State: Power [ Source:Any ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_ShowTabletCharging (338)

Pretty simple profile.  Just watches for any power source when the digital dash is active and runs its entry task.  When power is removed, it runs the exit task.

A1: Variable Set [ Name:%V3_BatteryDisplay To:%BATT% Do Maths:Off Append:Off ]

This single-line task uses Tasker's ability to display HTML in a text element to wrap the battery value in underline tags. I don't use Tasker's built-in %BATT value directly because I want to add the % at the end.

Exit: V3_ShowTabletNotCharging (339)
A1: Variable Set [ Name:%V3_BatteryDisplay To:%BATT% Do Maths:Off Append:Off ]

The exit task just removes the HTML tags.

There is a separate profile to track changes to the battery level.

Profile: V3_TrackBatteryLevel (356)
Event: Battery Changed
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_UpateBatteryLevel (357)

Again, very simple.  When the battery level changes while the dash is running, this profile runs its entry task.  There is no exit task.

A1: Variable Set [ Name:%V3_BatteryDisplay To:%BATT% Do Maths:Off Append:Off ]
A2: Variable Set [ Name:%V3_BatteryDisplay To:%BATT% Do Maths:Off Append:Off ] If [ %PACTIVE ~R V3_TabletPluggedIn ]

The first line just updates the %V3_BatteryDisplay variable when the tablet is not externally powered.  The second line does the same thing, but it checks to see if the V3_TabletPluggedIn profile is currently active.  If it is, the the HTML underline tags are added to the display variable. 

Tuesday, June 16, 2015

Digital Dash Documentation, Part 3: Tracking Connections

All three of the Bluetooth connections used by the system are actively monitored.  The audio link serves to start or stop the system (as described in the previous part of the documentation), but the network and OBD connections are watched simply to provide a status indicator.

The bottom center of the main screen contains the three connection icons, just above the audio controls:


The audio link is considered always active, but the icons for the other two connections may appear or disappear as controlled by the following profiles.

Profile: V3_ConnectToNetwork (297)
State: Variable Value [ %V3_DrivingMode Set ]
State: Not BT Connected [ Name:SCH-R970 Address:* ]
Enter: V3_ConnectToNetwork (298)

When the %V3_DrivingMode variable becomes SET by the V3_Startup task, as described earlier, this profile is fully enabled and is one of the first to activate.  It sees that there is no Bluetooth connection to my phone and attempts to remedy that by running its entry task.  The profile may also activate if the the network connection is lost at any time.

A1: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_Network Set:False Animation Time (MS):0 ]
A2: Secure Settings [ Configuration:SCH-R970 (9C:3A:AF:66:AB:DE) - Connect Package:com.intangibleobject.securesettings.plugin Name:Secure Settings Timeout (Seconds):0 Continue Task After Error:On ]
A3: Profile Status [ Name:V3_ConnectToNetwork Set:Off ]
A4: Wait [ MS:0 Seconds:5 Minutes:0 Hours:0 Days:0 ]
A5: Profile Status [ Name:V3_ConnectToNetwork Set:On ]

The above task sets the network connection icon visibility to false to indicate a lack of connectivity.  It then attempts to make a connection to the phone.  In order to keep the profile from firing constantly during this process, the profile itself is turned off for five seconds to give the system time to make a connection.  After that it is reactivated.  This means that the system will continue trying to make a connection every five seconds if its previous attempt was unsuccessful.  Currently, there is no limit on the number of tries (mainly because I haven't had a problem with this arrangement) but that could certainly be added.

Profile: V3_Network Connected (299)
State: BT Connected [ Name:SCH-R970 Address:* ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_NetworkConnected (300)

A1: Wait [ MS:0 Seconds:3 Minutes:0 Hours:0 Days:0 ]
A2: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_Network Set:True Animation Time (MS):0 ]

The above profile and task just notice that there is now a valid network connection and make the onscreen icon visible.  The three second delay, along with the five second delay in the connection routine, will make the icon blink slowly if the tablet is having trouble making the connection to the phone.

Because I use the system in two vehicles and want it to know which one it's connected to, I have two nearly identical profiles that listen for a connection to an OBD transmitter.  The profiles use the addresses of the adapters rather than the names since they are both called "OBDII" in the Bluetooth Devices list and renaming doesn't work due to an Android bug.  If I didn't care which one was connected, I could use a single profile with the name as the identifier and it would activate regardless of which one connected.

Profile: V3_Z3OBDTracker (372)
State: BT Connected [ Name:* Address:00:02:5B:00:A5:90 ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_BMW_OBDConnected (373)

This profile listens for the Z3 OBD adapter.

A1: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_OBD Set:True Animation Time (MS):0 ]
A2: Variable Set [ Name:%V3_CarLogo To:beam/BMW_logo.png Do Maths:Off Append:Off ]

The entry task just turns on the OBD onscreen indicator and sets the %V3_CarLogo variable to point to the BMW logo I have stored on the tablet.  The V3_RH scene has an image element tied to this variable, so when this task runs the system's main screen is branded with the BMW logo. 

Exit: V3_OBDDisconnected (374)
A1: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_OBD Set:False Animation Time (MS):0 ]

All the exit task does is turn off the OBD icon; the branding logo continues to be shown.

Profile: V3_JagOBDTracker (375)
State: BT Connected [ Name:* Address:00:0D:18:3A:67:89 ]
State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_Jag_OBDConnected (302)

This profile listens for the Jag OBD adapter.

A1: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_OBD Set:True Animation Time (MS):0 ]
A2: Variable Set [ Name:%V3_CarLogo To:beam/Jag.png Do Maths:Off Append:Off ]

The only difference in this entry task is the path to the logo; this one points to the snarling cat Jag logo.

Exit: V3_OBDDisconnected (374)
A1: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_OBD Set:False Animation Time (MS):0 ]

Both profiles share the same exit task.

Monday, June 15, 2015

Digital Dash Documentation, Part 2: Startup and Shutdown

This is the first part of the digital dash documentation that actually presents some code.  I'll be going through it in a fair amount of detail, but not generally line-by-line.

All of the project's profiles, except one, have two contexts; one of which is always %V3_DrivingMode is SET.  That keeps any of the profiles from firing unless I'm actually running the system.  For example, I may want to start Torque to change a layout or edit a vehicle profile and I don't need or want the overlays coming on at those times.

But, of course, there has to be an exception. The profile presented below (V3_AudioLinkActive) has only one context, so it can fire at any time.  All it does is listen for a connection to be made to the Miccus Bluetooth audio receiver.  When it sees that, the profile becomes active and runs its entry task (V3_Startup).  When the connection is lost (i.e. I shut down the receiver) the exit task (V3_Shutdown) is run.  It is, therefore, the starting and ending point for the project.

Here's the profile: 

Profile: V3_AudioLinkActive (370)
Restore: no
State: BT Connected [ Name:Miccus Mini-Jack Rx Address:* ]
Enter: V3_Startup (343)

And here's the entry task and it's breakdown, with explanations following the line(s) they are referring to:

A1: Keyguard [ Configuration:Keyguard dismiss Package:com.balda.keyguard Name:Keyguard Timeout (Seconds):0 ] 

The first line simply uses the Keyguard plugin to turn on the tablet.

A2: Variable Set [ Name:%V3_OnMain To:True Do Maths:Off Append:Off ]

Now the %V3_OnMain variable is set.  This variable is used to tell when the main screen is displayed.  Since the system starts up on that screen, this needs to be set. (Actually, it isn't really used at this point; I put it in because I'm going to need it for a planned future enhancement.)

A3: Create Scene [ Name:V3_TopMain Continue Task After Error:On ]
A4: Create Scene [ Name:V3_TopSources Continue Task After Error:On ]
A5: Create Scene [ Name:V3_TopEQ Continue Task After Error:On ]
A6: Create Scene [ Name:V3_LH Continue Task After Error:On ]
A7: Element Visibility [ Scene Name:V3_LH Element Match:LowFuel Set:False Animation Time (MS):0 ]
A8: Create Scene [ Name:V3_Bottom Continue Task After Error:On ]
A9: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_OBD Set:False Animation Time (MS):0 ]
A10: Element Visibility [ Scene Name:V3_Bottom Element Match:V3_Network Set:False Animation Time (MS):0 ]
A11: Create Scene [ Name:V3_RH Continue Task After Error:On ]
A12: Create Scene [ Name:V3_FavoriteSongs Continue Task After Error:On ]
A13: Create Scene [ Name:V3_Destinations Continue Task After Error:On ]
A14: Create Scene [ Name:V3_Menu_Button Continue Task After Error:On ]
A15: Create Scene [ Name:V3_MapSpeedometer Continue Task After Error:On ]

Lines 3-15 create an instance of (almost) all the scenes used in the system.  I do that here because many of them have elements that may need to be changed before they are displayed.  For example, lines 7, 9, and 10 hide some scene elements whose visibility is controlled by other profiles and tasks.

A16: Variable Set [ Name:%V3_FavoriteSongs To:Song Search Data1,Song Search Data2,Song Search Data3,Song Search Data4,Song Search Data5,Song Search Data6,Song Search Data7,Song Search Data8,Song Search Data9,Song Search Data10 Do Maths:Off Append:Off ]
A17: Variable Split [ Name:%V3_FavoriteSongs Splitter:, Delete Base:Off ]

These two lines set up the Favorite Songs list.  In line 16, you would replace every occurrence of "Song Search DataX" with enough information that PowerAmp could locate an individual song from that entry.  For example, you might put "Lucy" (with no quotes) as one entry if you wanted to find and play "Lucy in the Sky with Diamonds".  That would work as long as you have no other songs with the word "Lucy" in the title and had no artists with that name.  Line 17 turns the %V3_FavoriteSongs variable into an array that can later be entered with an index provided by the Favorite Songs menu.

A18: Variable Set [ Name:%V3_Compass To:N,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW Do Maths:Off Append:Off ]
A19: Variable Split [ Name:%V3_Compass Splitter:, Delete Base:Off ]

Lines 18 and 19 set up a variable array which is indexed from an AutoLocation profile/task to provide an on-screen compass.

A20: Variable Set [ Name:%V3_Destinations To:Address1, Address2, Address3, Address4, Address5 Do Maths:Off Append:Off ]
A21: Variable Split [ Name:%V3_Destinations Splitter:, Delete Base:Off ]

Lines 20 and 21 set up another array.  This one is used by the Destinations menu.  Again, you would replace each instance of "AddressX" with the full address that you would like to navigate to when you choose an entry from the menu.

A22: Variable Set [ Name:%V3_DrivingMode To:True Do Maths:Off Append:Off ]

%V3_DrivingMode is SET so that any other profiles in the system can now fire as needed.

A23: Variable Set [ Name:%V3_BatteryDisplay To:%BATT% Do Maths:Off Append:Off ]

Tasker's built-in %BATT Variable is converted to one that can be displayed on the screen.  The only real function of this line is to add the % after the value.

A24: AutoLocation Location [ Configuration:Starting Location Monitor
Location Report Name: V3_Compass
Interval: 1 seconds
Update Type: High Accuracy Package:com.joaomgcd.autolocation Name:AutoLocation Location Timeout (Seconds):60 Continue Task After Error:On ]

Line 24 starts the AutoLocation plugin running with a defined name (V3_Compass).  From this point on, it will track GPS data.  A profile will monitor for changes in that information and use it to display bearing and speed. (As will be explained in a later documentation entry.)

A25: WiFi [ Set:Off ]
A26: Media Volume [ Level:15 Display:Off Sound:Off ]
A27: Display Timeout [ Secs:0 Mins:0 Hours:8 ]
A28: Auto Brightness [ Set:Off ]
A29: Display Brightness [ Level:255 Disable Safeguard:Off Ignore Current Level:Off Immediate Effect:Off ]

The previous five lines simply configure some tablet parameters to the way I want them.

A30: Element Visibility [ Scene Name:V3_RH Element Match:V3_BrightnessAuto Set:False Animation Time (MS):0 ]

Since the system contains an onscreen brightness control that reflects the tablet's brightness state, I need to hide an element so that the display matches.  (In retrospect, I could have probably done this above when I was manipulating other elements.  Oh, well.)

A31: Launch App [ App:Torque Data: Exclude From Recent Apps:Off Continue Task After Error:On ]

Here we finally get around to starting Torque.  At this point the system is mostly (but not entirely) up and running and it's time to see the interface. Because we set the %V3_DrivingMode variable up above, the profile that controls the overlays is able to fire now.  Some things, like the network connection, OBD connection, and temperature will not be ready yet, but they are beginning to come online. Torque also begins writing data to its log file as soon as the OBD connection is made.
  
A32: Perform Task [ Name:V3_TimeAndTorque Priority:2 Parameter 1 (%par1): Parameter 2 (%par2): Return Value Variable: Stop:Off ]

The last step of the Startup procedure is to begin executing a low-priority, looping task.  This task repeats about every 30 seconds and is used to update the clock display and bring in the "Estimated Distance to Empty" value from Torque.

Within a few seconds, all the connections should be made and all the initial data displayed.  We are now at the the normal steady-state for the system.



When the connection to the Miccus is terminated, the V3_AudioLinkActive profile becomes inactive and runs its exit task, below.

Exit: V3_Shutdown (344)

A1: Variable Clear [ Name:%V3_DrivingMode Pattern Matching:Off ]

The first thing we do is clear the %V3_DrivingMode variable so that none of the system profiles can fire again.

A2: Go Home [ Page:0 ]

Now we display the tablet's home screen.

A3: Destroy Scene [ Name:V3_TopMain Continue Task After Error:On ]
A4: Destroy Scene [ Name:V3_TopSources Continue Task After Error:On ]
A5: Destroy Scene [ Name:V3_TopEQ Continue Task After Error:On ]
A6: Destroy Scene [ Name:V3_LH Continue Task After Error:On ]
A7: Destroy Scene [ Name:V3_Bottom Continue Task After Error:On ]
A8: Destroy Scene [ Name:V3_RH Continue Task After Error:On ]
A9: Destroy Scene [ Name:V3_FavoriteSongs Continue Task After Error:On ]
A10: Destroy Scene [ Name:V3_Destinations Continue Task After Error:On ]
A11: Destroy Scene [ Name:V3_CancelOverlays Continue Task After Error:On ]
A12: Destroy Scene [ Name:V3_Menu_Button Continue Task After Error:On ]
A13: Destroy Scene [ Name:V3_MapSpeedometer Continue Task After Error:On ]

Lines 3-13 destroy all the previously created scenes.

A14: Display Timeout [ Secs:7 Mins:0 Hours:0 ]

Line 14 sets the display timeout so that the system will turn itself off when it completes the exit task.

A15: Auto Brightness [ Set:On ]

AutoBrightness is returned to its default value.

A16: AutoLocation Location [ Configuration:Stopping Location Monitor
Location Report Name: V3_Compass
Update Type: No Power Package:com.joaomgcd.autolocation Name:AutoLocation Location Timeout (Seconds):60 Continue Task After Error:On ]

Location tracking is stopped.

A17: Stop [ With Error:Off Task:V3_TimeAndTorque ]

The task that updates the time and "Distance to Empty" check is stopped.

A18: Send Intent [ Action:org.prowl.torque.REQUEST_TORQUE_QUIT Cat:None Mime Type: Data: Extra: Extra: Package: Class: Target:Broadcast Receiver Continue Task After Error:On ]

Torque is shut down and stops logging its data.

A19: Secure Settings [ Configuration:SCH-R970 (9C:3A:AF:66:AB:DE) - Disconnect Package:com.intangibleobject.securesettings.plugin Name:Secure Settings Timeout (Seconds):0 Continue Task After Error:On ]

The Bluetooth connection to the phone is terminated.  This will cause the phone to run its own shutdown sequence and turn everything off.

A20: WiFi [ Set:On ]

Since we don't have network through the phone any more, we need to be ready to connect via WiFi.

A21: Run Shell [ Command:/data/data/burrows.apps.busybox/app_busybox/tail -1 /storage/emulated/0/torqueLogs/trackLog.csv Timeout (Seconds):0 Use Root:Off Store Output In:%obd_log Store Errors In: Store Result In: Continue Task After Error:On ]
A22: Delete File [ File:torqueLogs/trackLog.csv Shred Level:0 Use Root:Off Continue Task After Error:On ]
A23: Wait [ MS:0 Seconds:3 Minutes:0 Hours:0 Days:0 ]
A24: Write File [ File:torqueLogs/trackLog.csv Text:%obd_log Append:Off Add Newline:On Continue Task After Error:On ]

The previous four lines handle Torque's log data between runs of the system.  Since I have Torque set up to use the same log file each time, I want to delete it so it doesn't get too large.  However, if I just do that, the next time the Digital Dash starts up, it will see a null entry for the Distance to Empty value and think that I'm out of gas.  It announces that with a verbal and visual display, which can be a bit startling and I'd rather not have that come on.  So, I read the last line of the log, delete the file, and then write a new one with same name that contains only the line I just read.  That way, the systems starts up right where it left off with the same data.

A25: Wait [ MS:0 Seconds:10 Minutes:% Hours:0 Days:0 ]
A26: Display Timeout [ Secs:0 Mins:2 Hours:0 ]

All of these tasks take some time, and some of them (like turning on WiFi) can cause screen activity.  The Wait command just gives those things some time to complete.  And at the end of 10 seconds, the tablet begins to power down. As a last step, we then set the display timeout back to two minutes.

At this point the system is shut down and everything is back to normal.




Sunday, June 14, 2015

A Few More Changes

I just can't stop fooling with this thing; Tasker is very addictive.

Although I created the system specifically for use in the Z3, I've also used it a few times in my Jag, especially since I found that there's a small gap at the top of the center console that can be used as an anchor point for the tablet mount.

The last time I did this I noticed that it seemed a bit odd to have the BMW logo down in the corner, so I made a small change.  I went out and grabbed a Jag logo (the snarling face version), cropped it to be a square, and transferred it to the tablet.  Then I changed the logo image element on the main screen to be a variable (%V3_CarLogo) instead of a hard-coded path.

I already had a pair of profiles tracking connections to the OBD transmitters in each car so that no matter which one linked up, the connection icon on the screen would come on.  It was a simple matter to add just one line to each of the entry tasks that sets the %V3_CarLogo variable to the proper path for the right image.

It's a completely aesthetic change, with no functional difference, but at least the interface is appropriately branded for each car.

The other change I made is even more whimsical.

Most people that know me think I'm a bit of a pyro; and they're not wrong.  Our house has a wood burning fireplace, but we've added a marble fireplace out on the patio, a gel fuel fireplace off the kitchen, a firepit at the back of the yard, a propane fire table on the back porch, and several portable gel fuel burners that we move around as desired.

We had some friends over this past weekend and were showing them a few of these.  Their reaction? "All you need now is a fireplace in your car."  And they were right.

A quick search on Google Play turned up all kinds of options, so I downloaded the free version of "Fireside" and made it part of the system.

Now, a long tap on the clock element on the main screen launches a virtual fireplace; just the thing for parking under the stars on these cool summer nights. An invisible scene that covers the entire screen goes back to the main display when I tap on it.

Not sure what I'll do next,  but a virtual aquarium is a real possibility.

Friday, June 12, 2015

Digital Dash Documentation, Part 1: Apps and Add-ons



This is the first part of my digital dash documentation.  Although the digital dash is, of course, a Tasker project, it relies on a number of other pieces for its functionality.  This section of the documentation lists those and briefly describes what they’re used for. Later sections will break down the Tasker code in great detail.

Apps

Tasker – Obviously.  Without this app I couldn't have created the project.  The mere existence of Tasker makes Android vastly superior to IOS for projects of this type.
Torque – The foundation app.  Provides engine information, mileage, and GPS data.  Other information on the main screen is provided by scenes overlaid on Torque.
Google Maps – Used for Navigation and just generally knowing where I am.
MyRadar – Provides localized weather radar; important when you are out in a convertible and there are dark clouds coming up in front of you.
TWC – The Weather Channel app.  Gives more detail about localized weather conditions and forecasts.
GPS Status – Used mainly to download updates of GPS Assist data.  It also has a wealth of information about satellite connections that is best viewed when parked.
PowerAmp – Local music playback.  Chosen because it is well-supported via Tasker actions.
Pandora – Internet radio.  Also easy to work with in Tasker.
Scanner Radio – Provides localized access to LEA radio and weather alerts.

Add-ons

ActionBox – Used to control PowerAmp's EQ functions
AutoInput – Used to simulate screen taps to turn multi-touch operations into programmatically controlled functions.
AutoLocation – Used to get GPS bearing data that drives the on-screen compass.  Also used to get GPS speed data for display over Google Maps.
AutoNotification – Used to scrape track and artist info from Pandora’s “now playing” notification and bring it into Tasker.
AutoRemote – Used to send messages from the phone to the tablet. (Mainly just temperature data at the moment.)
AutoShare – Used to play specific songs in PowerAmp by sending a “Search and Play” intent.  It also acts as the media control interface for PowerAmp.

(As you may have guessed from the last five entries, I’m a big fan of joaomgcd's AutoApps suite of Tasker plugins.)

BusyBox - Used for its inclusion of the “tail” shell command which allows for the reading of the last line of a file.  This is used to read Torque’s data log to bring in the “Estimated Distance To Empty” value to Tasker.
Keyguard - Used to turn on the tablet and phone.
Secure Settings – Used to initiate the Bluetooth tethering connection between the phone and the tablet.


Tuesday, June 09, 2015

Digital Dash - Revised and Available as a Tasker Project

I've revised my digital dash project (again) and made it available as a Tasker project for anyone who might like to fool around with it.

Most of the changes were behind the scenes: I put everything into one project, got rid of the deprecated code, used a better naming scheme, and generally simplified and cleaned up everything.  However, there were a few interface changes as well.

I recently added an iKross Ultra Compact 2in1 window mount holder to my setup, so now my phone is mounted to the driver’s side wing window.  That means it’s always in view, so I can more easily see and hear when I get calls and texts.  So, I eliminated the functions that push those types of notifications to the tablet.  I still send out an auto-reply to texts saying that I’m not going to respond, however.  With the phone always visible, I now have it starting up and running Waze so I always have a map visible.  I still use Google Maps on the tablet for navigation, though.  I just like Waze’s road hazard notifications.

As part of simplifying the system, I re-did the top menu bar.  Where before it had been a single scene with lots of elements that I turned on and off, it’s now three individual scenes that I show and hide as needed.  With that, I decided that the EQ settings shouldn’t really be a top level function since they only affect PowerAmp.  Accordingly, I moved their access.  They are now called up by a long-tap on the PowerAmp button.  A long-tap on the main screen (which is what used to call up the EQ) now brings up the favorite songs menu (previously done by swiping).  The swipe function was removed.
The only other interface change has to do with the favorite songs and destinations menu.  Before, if you called one of those up and decided you didn’t want to do anything, you tapped the BMW logo to cancel.  Now, you can tap anywhere on the screen (except the menu itself, of course) to cancel the function.  That also works if you accidentally call up the audio sources panel.

If you do decide to load up the project and take a look, you’ll find a few things that don’t seem to make much sense.  For example, the way I handle choosing a destination or playing a favorite song seems unnecessarily complex, and there are some variable and elements that don’t seem to be used at all.  That’s because I’m planning for some future enhancements and those things will make those a lot easier.

The zip file, which you can download from: https://dl.dropboxusercontent.com/u/10986031/V3_Dash.zip

Contains the Tasker project and the graphics I used.  You’ll need to relink the graphics in the scenes, but everything should be there.  However, this zip doesn't have the phone side of things.  I’m working on that and will make it available later.  In the meantime, all you’ll be missing really is the routine that sends phone temp to the tablet.  You can easily replace that with something like the WeatherAce plugin to get local temps.

It will take some fooling around to get this working since it is tightly tied to my specific hardware and software.


I intend to do a few posts documenting the system in detail.  Not that I think anyone is really that interested in this, but I know that sooner or later I’m going to have a bad crash, a failed system update, or even a new device and I might not be able to restore from a backup.  And if I need to recreate this system, I want to have more than my memory to go on. 

Wednesday, April 15, 2015

Solving the Z3 Subwoofer Buzz

Over the weekend I found a zero-cost solution to an audio problem that has been bothering me ever since I got the car.  There was a terrible buzzing, rattling sound coming from the subwoofer any time you turned up the volume on a song with lots of bass.  “Spirit in the Sky”, for example, sounded like there was a swarm of bees living in the subwoofer.

I figured that the speaker was either broken or worn out and what little reading I had done on the subject seemed to indicate that there was no easy fix.  BMW had used speakers for which there is no easily available drop-in replacement.  Everything that I read talked about having to modify the speaker enclosure with a hacksaw or Dremel tool; not something I was anxious to tackle.  To make matters worse, there had been several iterations of the sound system and it wasn’t real clear exactly what I’d see when I opened things up.

In the beginning the Z3 only had two speakers; one in each footwell, but by the time my car was manufactured, each side of the car had a footwell speaker, a fill-in speaker at the top front of the door, and another speaker on the rear cabin wall which fired directly into the back of the seat.  In addition, there is a subwoofer in the middle, between the seats, where there used to be a lockable storage compartment.

I’d seen the speaker grille for the subwoofer, of course, and I just assumed that if I were to take that off, I’d see the speaker.  But as it turns out, the situation is more complicated than that.
Behind that grille, there is really just a padded, empty space.  The subwoofer actually sits deeper in the rear wall in a sealed enclosure that can only be accessed by removing a panel at the top, between the roll bars.  And it isn’t even just a single speaker.  Instead, there are two 6.25” speakers, sitting back to back and wired in reverse phase.  The rear-facing speaker is a helper that adds strength to front-facing one.  The enclosure has an oval port that points forward into the cavity behind the speaker grille and lets the sound out.

But it doesn’t come out directly.  Pushed into that port is tuned plastic horn that looks something like an upside-down “L”.  The sound exits the port, goes into the horn, is directed to the bottom of the enclosure, and hence, out through the speaker grille. 

The problem comes from the way the horn is attached to the port: it isn’t.  It’s just pushed in and held by friction.  And it’s not a very tight fit.  So when the subwoofer cranks up and starts pushing significant air through the port, the horn moves along with it, rattling and buzzing against the grille.
The fix, fortunately, is very simple.  The grille pops off easily when you pull up at the bottom on either side.  Then the horn can be taken out, again very easily.

I took mine out and wrapped some closed-cell, self-adhesive weather stripping around it at the points where if could contact the enclosure.  Then I put the horn back in, snapped on the grille, and cranked up the bass.

The difference was amazing.  The sound was clean and tight with no annoying buzz.  The whole thing took maybe 10 minutes.

I know the Z3 sound system has been criticized as being weak and underpowered, but, honestly, the only problem I had with it was the subwoofer buzz.  As I’ve said before, the only time the stereo is on is when we’ve got the top down and are listening to classic rock that we are very familiar with.  It’s not the reproduction so much as it is the ambience, so I’m perfectly content with it.

I’d like to thank Jon T and his “Z3 Page O' Fun!” (http://www.ackthud.net/z3/) for sharing this fix (http://www.ackthud.net/z3/2000/Subwoofer/subwoofer.html). You can see some good pictures of the solution on his pages.