The Internet of Thing – Hypoxia

February 22, 2015

The second episode of the “Internet of Thing” focusing on Hypoxia and rapid decent situations. URL: https://www.youtube.com/watch?v=sJVK1RPC3kY

The Internet of Thing

February 19, 2015

The first episode in a 5 part series I am calling “The Internet of Thing”. Enjoy.

http://youtu.be/RFpJId3vPMo

Forgotten Blog Spot…

May 1, 2012

A while ago I stopped using this blogspot and switched my focus toward blogging internally (on the Sales Force Chatter blog) and writing corporate articles and white papers.  I would like to resurrect this blog and use it for some of my outside/ecology issues.  Look for updates in the coming weeks.

Snow Weight(ing)

February 13, 2010

Just to dispel rumors that I don’t know how to have fun….

We just had another big (well big for us) snow storm.  I did my driveway and two neighbors.  That got me to thinking about a just how much snow I shoveled (OK, plowed) over the past two days.

Now, in fairness, it actually got me to rethinking about this problem, since I actually worked out the math and wrote a program to do this several years ago.  This being a new blog, I reserve the right to republish old work.  So….

If you count the linear feet in single car widths, I cleared 280′ of driveway. A quick look up on the internet shows that snow ranges anywhere from 10 lbs (fresh fluffy) to 30 lbs (water laden) per cubic foot.  We got a little over a foot.  I figued this snow was around a 20, maybe more.  Therefore, the weight of this much snow is:

weight (lbs) = length (ft) x width (ft) x depth (ft) x weightFactor (lbs/cf)  = 120 x 10 x 1.2 x 20

or a staggering 67,200 lbs of snow.  That’s the equivalent of moving 13 full sized, fully loaded Chevy pickup trucks.  Around twice that number for empty (curb weight) trucks.

If you are curious about how much snow you shoveled/plowed, the following code with do the calculation for you…

public class SnowWeighting {

 private static final double curbWeight = 5100; // weight of a chevy 1500 pickup truck
 private static final double drivewayWidth = 10.0;     // feet

 public static void main(String[] args) {
 String usage = "";
 usage += "Usage: java com.kkranz.utils.SnowWeighting length depth weight\n";
 usage += "Where:\n";
 usage += "    length - linear feet of 10 ft wide driveway cleared\n";
 usage += "    depth  - depth of the snowfall in feet\n";
 usage += "    weight - snow pounds per cubic feet.  \n";
 usage += "         Suggestions: 10 (new/fluffy) - 30(wet/compacted)";

 if (args.length != 3) {
    System.err.println(usage);
    System.exit(0);
 }

 double linearFeet = 0; // linear feet of 10 ft wide driveway cleared
 double weightPerCF = 15.; // lbs per cubic foot for snow (suggest: 10 - 30)
 double snowDepth = 0; // in feet

 try {
    linearFeet = Double.parseDouble(args[0]);
 } catch (NumberFormatException e) {
    System.err.println("illegal linear foot value");
    System.exit(0);
 }
 try {
    snowDepth = Double.parseDouble(args[1]);
 } catch (NumberFormatException e) {
    System.err.println("illegal snow depth value");
    System.exit(0);
 }
 try {
    weightPerCF = Double.parseDouble(args[2]);
 } catch (NumberFormatException e) {
    System.err.println("illegal pounds per cf value");
    System.exit(0);
 }

 if (weightPerCF < 10 || weightPerCF > 30) {
    System.err.println("Warning: not a realiztic snow weight...");
 }

 double totalWeight = linearFeet * drivewayWidth * snowDepth * weightPerCF;
 double truckEquiv = totalWeight / curbWeight;

 System.out.println("Total wight (in lbs) of snow removed: " + totalWeight);
 System.out.println("Equiv number of pickup trucks moved: " + truckEquiv);
 }
}

Which Jar – Take 2

February 11, 2010

Thanks to a seed put in my head from a friend.  Here is an update to the shell script version of whichJar which will search either a directory (as was posted originally) or search along the CLASSPATH.  Humm, makes me wonder why I expended sooo much code to create the Java version way back when?  Well, the Java code version did use reflection – which was cool….

!/usr/bin/ksh
searchClasspath=0
if [[ x$1 == x-c ]]
then
 searchClasspath=1
 shift 1
fi
if [[ x$1 == x ]]
then
 echo "usage $0 classspec"
 echo "$0 /com/abc/someclass.class"
 exit 0
fi
if [[ $searchClasspath == 1 ]]
then
x=$(echo $CLASSPATH | sed -e "s%:% %g")
for i in $x
do
 y=$(echo $i | grep -i jar)
echo $y
 z="$z $y"
done
echo $z
for i in $z
do
 echo $i
 jar -tvf $i | grep $1
done
else
for i in $(find . -name \*jar)
do
 echo $i
 jar -tvf $i | grep $1
done
fi

Empirical Solar Power Measurement

February 10, 2010

I recently installed a 10K solar photovoltaic system on my west facing roof.

The first obvious question that arises (as the installer’s trucks are leaving the driveway) is: just how much will I save?

[update: the above picture was taken on a sunny day one week after the winter solstice.  Note the extent of the shading on the roof.  This is basically the worst it gets.  The 3×3 grid to the right has very diffuse shading. These panels and the one on the bottom to the left make up one string.  Therefore; this string is basically shutdown – leaving the other 3 strings generating power at full capacity.  ]

While it is way too early for me to know the full extent of the yearly savings, the graph below depicts the monthly savings based on usage data for the past 7 December’s (yes,  that’s 49 dog years – clearly I’ve been think’in/plan’in ’bout this for a while).  December is a noteworthy month because it represents my most diminished power generation.  This is partly because of the sun being lower in the sky but also due to the fact that, given the height and location of some trees, it is the month where I experience the most diffuse shading.

So, what does this chart depict.  First, as can be seen, I had a significant downward trend in energy consumption starting in 2008.  This was due to the conversion of the most used lights in my house to CFL and LED and the addition of Smart Power Strips (see my Sun Blog for details).  There were other changes, like the solar pool heater I installed on the roof.  That and the LEDs made the most noticeable differences (even when you consider the purchase costs – subject of another blog).  That said, the KWH consumption for Dec 09 is clearly 1/2 that of ’08.

The next chart depicts my energy consumption for the 3 month period Nov-Jan (the most data I have to date).

This chart interestingly shows a similar (but slightly more striking) reduction.

The next question I need to answer is: does it pay to top or otherwise chop down the offending trees?  If you ask the guys from the solar company the stock answer is: “chop’em down”.  But it’s not that simple.  This is a classic min/max equation.  If you cut the trees down, you generate more energy – hence save more money, but it costs money to chop the trees down.  It gets more difficult (muddy) if you top the trees.  It then becomes more of a an equation with a hysteresis.  When the tree hight remains below the shading level, it’s a min/max.  Once the trees grow to shading height again, it becomes a differential equation. Then there is the issue of destroying environmentally friendly trees.  Which only exacerbates the problem if the ROI of topping/cutting are minimal or negative.

My guess (only option?) is to continue to plot these seasonal 3 month trends.  Maybe, if I see the slope of the differential curve significantly increase in the Dec time frame, I can figure out just how much these trees are costing me.

[update: I should be clear here.  I am talking about taking the 2nd derivative of this measurement.  aka: the delta to the 3 month delta snapshots.  Is this more clearer?  Clear as mud? ]

My goal is to come up with a cost/savings calculator.  It would take in:

  • the months and percentage shading the trees are generating
  • The cost to top the trees and the anticipated time to grow back to their org/current height (yes, this is problematic)
  • the cost to chop down the trees
  • the cost of a KWH for your utility

It would then compute the return on investment.  I’m an EE/SW engineer with a decent math/stats background.  I just don’t know if I have all the smarts I need to do the afore mentioned calculations.  If anyone has any insight, please do share them with me.  My goal is to stop people from blindly chopping down trees if the return on investment is minimal (a judgment call) or negative (y’d have to be an idiot to do it), while the harm to the environment is tangible.

Which Jar

February 10, 2010

I was faced with a problem the other day – one that I did not have to deal with for a long time.
Namely, I needed to figure out which JAR file contained a class file I needed.  I knew the file
existed somewhere within the app server installation.

To solve this, relatively easy, problem, I put together the following snipit of code…

for i in $(find . -name \*jar)
do
echo $i
jar -tvf $i | grep $1
done

Basically this searches for every JAR, cracks it open and then looks for the path/classname that matches the search topic.

This brought back (somewhat horrific) memories of a program I wrote around a decade ago.  WhichClass was part of my RRTUtils open source project.  It did a similar  thing (finding what JAR a class belonged) but it did it along the CLASSPATH.
The situation back then was that I would be at a POC, had little knowledge of the client’s environment, didn’t really want much knowledge, but needed results.  The code below does just that.  You should be able to cut/paste this into your favorite java editor.

package com.kkranz.utils;

import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
import java.io.*;
import java.lang.reflect.*;

/**
* <PRE>
*
* Name:
* com.kkranz.utils.WhichClass.class
* <BR>
* Title:
* Which Class
* <BR>
* Usage:
* java com.kkranz.utils.WhichClass -sep chr -v[erbose] -h[elp] classname classpath
* <BR>
* Where options are:
* <BR>
* -sep val     Specifies the separator character used in the classpath arg
* Default path separator value is system dependent (run with -h to see value)
* -v[erbose]   Increase verboseness level, example:
* -v            Echo’s input params for verivication.
* -v -v        also lists the names of all directories and files it searches.
* -v -v -v    also lists the contents of all JAR and ZIP files.
* -h[elp]      Display this on-line help message
* classname:  The name of the target .class file
* classpath:  The intended class path to search (not necessarily the system CLASSPATH)
*
* <BR>
* Description:
* Searches the input classpath for all occurrences of the specified classname.  This utility was
* intended to be used when trying to debug a java eWay or BOB start-up error.
* <BR>
* Warnings/Notes:
* 1) You may use either the “\” or “/” separator characters within the class name and path
* 2) Surround your classpath with quotes (“) if it contains spaces or special characters
* 3) If a class is found in multiple directories/jar files, it will be listed multiple times
* 4) The final list of classes found is sent to STDOUT, all verbose output to STDERR – good for script support
* <BR>
* See Also:
* none
* <BR>
* Examples:
* To find this program (WhichClass) in a given classpath (egate/client/classes, egate.jar, and rrt.jar) enter…
* java com.kkranz.utils.WhichClass com/kkranz/utils/WhichClass.class “/egate/client/classes;/egate/client/classes/egate.jar;/egate/client/classes/rrt.jar”
* Note the use of either file separator (\ or /) has no effect on the results
*
* To find a pragam with the current system classpath…
* java com.kkranz.utils.WhichClass com/kkranz/utils/WhichClass.class “$CLASSPATH”
* <BR>
*
* </PRE>
*/
public class WhichClass {
/** the name of this class file at runtime – used for verbose output */
private java.lang.String thisName = null;
/** list of all the directories, JAR files, and/or ZIP files that had instances of the target class */
private java.lang.StringBuffer foundList = null;
/** the name of the targe class in DOS slash format */
private String dosName = null;
/** the name of the targe class in UNIX slash format */
private String unixName = null;
/** classpath to search – will not serarche the system’s classpath by default */
private String classPath = null;
/** the path separator needed to take apart the input classpath */
private String pathSeparator = null;
/** determines the amount of status output to STDERR that is generated */
private int verboseLevel = 0;
/** loosens up the comparison algorithm to, basically, check the end of the string for a match */
private boolean looseFit = true;
/** used to printout variables for debugging */
private static final boolean DEBUG = false;
/** used to display just the jar file name */
private boolean silent = false;

/**
* Default constructor.
*/
public WhichClass() {
super();
this.thisName = this.getClass().getName();

dosName = null;
unixName = null;
classPath = null;
Properties props = new java.util.Properties(System.getProperties());
pathSeparator = props.getProperty(“path.separator”);
verboseLevel = 0;
}
/**
* Allows programmer to control the internal settings.  Good for use outside of this main().
*/
public WhichClass(String cName, String cPath, String pSep) {
super();
this.thisName = this.getClass().getName();

dosName = cName.replace(‘/’, ‘\\’);
unixName = cName.replace(‘\\’, ‘/’);
classPath = cPath;
pathSeparator = pSep;
verboseLevel = 0;
}
/**
* helper method to process appending to the found list
*/
private void flAppend(String name) {
if (foundList == null) {
// first entry.  Add it as “name”
foundList = new StringBuffer(“”);
foundList.append(name);
} else {
// entries exist, add them as <separator> value
foundList.append(pathSeparator + name);
}
}
/**
* Returns a list of all files/directories that contain the target class.  Set to
* a zero length string if none found.
* @return StringBuffer
*/
public StringBuffer getFoundList() {
return foundList;
}
/**
* Sets the verbose level independent of the main’s switch setting – good for use outside the main()
* @return int
*/
public int getVerboseLevel() {
return verboseLevel;
}
/**
* Searches the input classpath for the class file specified.  The classpath
* is parsed based on the input path separator – which might or might not be
* the native separator for the system that this process is running on.
*
* The name(s) of the directory or file (in the case of a zip/jar) that contains the
* target class file is returned.
*/
public void locateClass() {
String thisMethod = thisName + “.locateClass(): “;
foundList = new StringBuffer(“”); // clear out the found list;

StringTokenizer classPathList = new StringTokenizer(classPath, pathSeparator);

while (classPathList.hasMoreTokens()) {
String nextTarget = classPathList.nextToken();

if (nextTarget.toLowerCase().endsWith(“.jar”) || nextTarget.toLowerCase().endsWith(“.zip”)) {
// a jar or zip file
JarFile jf = null;
ZipFile zf = null;
Enumeration jEntries = null;

if (nextTarget.toLowerCase().endsWith(“.jar”)) {
if (verboseLevel > 1) {
System.err.println(thisMethod + “searching JAR ” + nextTarget + “…”);
}
try {
jf = new JarFile(nextTarget, false);
jEntries = jf.entries();
} catch (java.io.IOException e) {
System.err.println(thisMethod + “error while reading JAR:” + nextTarget + “\n” + e.getMessage());
return;
}
} else if (nextTarget.toLowerCase().endsWith(“.zip”)) {
if (verboseLevel > 1) {
System.err.println(thisMethod + “searching ZIP ” + nextTarget + “…”);
}
try {
zf = new ZipFile(nextTarget);
jEntries = zf.entries();
} catch (java.io.IOException e) {
System.err.println(thisMethod + “error while reading ZIP:” + nextTarget + “\n” + e.getMessage());
return;
}
}

while (jEntries.hasMoreElements()) {
Object anEntry = jEntries.nextElement();
String jfClass = anEntry.toString();
if (jfClass != null) { // in case there is a difference between JAR files created under UNIX
// and ones in DOS (I don’t think there is) check for both – either
// one will work
String dosClass = jfClass.replace(‘/’, ‘\\’);
String unixClass = jfClass.replace(‘\\’, ‘/’);
//String packageName = unixClass.substring(0, unixClass.lastIndexOf(‘/’)).replace(‘/’, ‘.’);
//String rootName =unixName.substring(0, unixName.indexOf(‘.’));
if (verboseLevel > 2) {
System.err.print(unixClass + ”                                                  \r”);
};
if (dosClass.compareTo(dosName) == 0 || unixClass.compareTo(unixName) == 0) {
if (verboseLevel > 0) {
System.err.println(thisMethod + “Found ” + unixName + ” in ” + nextTarget);
};
flAppend(nextTarget);
}
if (looseFit) {
if (DEBUG) {
System.out.println(“\n\n\n”);
System.out.println(“unixClass ” + unixClass);       //  a/b/c/foo.class
System.out.println(“unixName  ” + unixName);        //  foo.class
System.out.println(“dosClass  ” + dosClass);        //  a\b\c\foo.class
System.out.println(“dosName   ” + dosName);         //  foo.class
System.out.println(“jfClass   ” + jfClass);         //  a/b/c/foo.class
System.out.println(“nextTarget ” + nextTarget);     //  /dirA/dirB/dirC/bar.jar
System.out.println(“anEntry   ” + anEntry);         //  a/b/c/foo.class
//System.out.println(“package   ” + packageName);     //  a/b/c/
//System.out.println(“root name ” + rootName);        //  foo
}

// OK to assume just the class name is being searched
if (unixClass.toLowerCase().endsWith(unixName.toLowerCase()) == true) {
if (silent) {
System.err.println(nextTarget);
}else {
System.err.println(“Loosely found ” + unixName + ” as ” + jfClass + ” in ” + nextTarget);
}
}

//if (searchMethods(anEntry, unixName)) {
//    System.err.println(thisMethod + “Method found ” + unixName + ” as ” + jfClass + ” in ” + nextTarget);
//}
//flAppend(nextTarget);
}
}
}

} else { // must be a directory
if (verboseLevel > 1) {
System.err.println(thisMethod + “searching directory ” + nextTarget + “…”);
};
String fullyQualifiedName = nextTarget + “/” + unixName;
File f = new File(fullyQualifiedName);
if (f.exists()) {
if (verboseLevel > 0) {
System.err.println(thisMethod + “Found ” + unixName + ” in ” + fullyQualifiedName);
};
flAppend(fullyQualifiedName);
}

}
}

return;
}

private boolean searchMethods(Object inObj, String targetMethodName) {
Class inClass = inObj.getClass();
Method getInMethod  = null;

Method[] methods = inClass.getDeclaredMethods();
System.out.println(inClass.getName());
for (int i=0; i<methods.length; i++) {
Method m = (Method) methods[i];

if (m.getName().compareTo(targetMethodName) == 0) {
System.out.println(“method is: ” + methods[i].getName());
return true;
}
}
return false;
}

/**
* Allows you to override (reset) the name, path, and separator defined by the constructor
*/
public void locateClass(String cName, String cPath, String pSep) {
StringTokenizer classPathList = new StringTokenizer(classPath, pathSeparator);

dosName = cName.replace(‘/’, ‘\\’);
unixName = cName.replace(‘\\’, ‘/’);
classPath = cPath;
pathSeparator = pSep;

this.locateClass();

return;
}
/**
* Starts the application.  See javadoc for class for complete details or run with -h option.
* @param args an array of command-line arguments
*/
public static void main(java.lang.String[] args) {
WhichClass wc = new WhichClass();

String thisMethod = wc.thisName + “.main(): “; // used for verbose output

boolean helpFlag = false;
String usage = “java ” + wc.thisName + ” -exact -sep chr -v[erbose] -h[elp] classname classpath”;
int ArgSpec = 2; // minimum number of expected arguments
int switchCount = 0; // number of switches found
boolean CLIError = false; // user invocation error

for (int i = 0; i < args.length; i++) {
if (args[i].equals(“-verbose”) || args[i].equals(“-v”)) {
wc.verboseLevel++;
switchCount++;

} else if (args[i].equals(“-sep”) || args[i].equals(“-separator”)) {
wc.pathSeparator = args[++i]; // override separator char with user’s value
switchCount+=2;

} else if (args[i].equals(“-help”) || args[i].equals(“-h”)) {
helpFlag = true;
switchCount++;

} else if (args[i].equals(“-s”)) {
wc.silent = true;
switchCount++;

} else if (args[i].equals(“-exact”)) {
wc.looseFit = false;
switchCount++;

} else if (!args[i].startsWith(“-“, 0)) {
// reached the end of the switch options,
// OK to stop processing switches
break;

} else if (args[i].startsWith(“-“, 0)) {
System.err.println(“Illegal switch: ” + args[i]);
CLIError = true;
switchCount++;
}
}

if (helpFlag) {
System.out.println(
usage
+ “\n\n”
+ ”   -exact       The input class/package name must match exactly (default: loose fit)\n”
+ ”   -sep val     Specifies the separator character used in the classpath arg\n”
+ ”                Default path separator value: ‘” + wc.pathSeparator + “‘\n”
+ ”   -v[erbose]   Increase verboseness level\n”
+ ”     -v            Echo’s input params for verivication.\n”
+ ”     -v -v        also lists the names of all directories and files it searches.\n”
+ ”     -v -v -v    also lists the contents of all JAR and ZIP files.\n”
+ ”   -h[elp]      Display this on-line help message\n”
+ ”    classname:  The name of the target .class file\n”
+ ”    classpath:  The intended class path to search (not necessarily the system CLASSPATH)\n”
+ “\nNotes: \n”
+ ” 1) You may use either the \”\\\” or \”/\” separator characters within the class name and path\n”
+ ” 2) Surround your classpath with quotes (\”) if it contains spaces or special characters\n”
+ ” 3) If a class is found in multiple directories/jar files, it will be listed multiple times\n”
+ ” 4) The final list of classes found is sent to STDOUT, all verbose output to STDERR\n – good for script support”
+ “\nExamples: \n”
+ ”    To find this program (WhichClass) in a given classpath (egate/client/classes, egate.jar, and rrt.jar) enter…\n”
+ ”         java ”
+ wc.thisName
+ ” com/kkranz/utils/WhichClass.class \”/egate/client/classes;/egate/client/classes/egate.jar;/egate/client/classes/rrt.jar\”\n”
+ ”    Note the use of either file separator (\\ or /) has no effect on the results\n\n”
+ ”    To find a program with the current system classpath…\n”
+ ”         java ”
+ wc.thisName
+ ” com/kkranz/utils/WhichClass.class \”$CLASSPATH\”\n\n”
+ ” note how the use of froward and backward slashes doesn’t matter.\n”
+ ” Also note that the class is specificed by a file system path – not a package statement.”
+ “”);
System.exit(0);
}

int totalArgs = args.length – switchCount;
int firstArgOff = switchCount;

if (ArgSpec != totalArgs) {
System.err.println(totalArgs + ” arguments found ” + ArgSpec + ” expected\n”);
System.err.println(“Usage: ” + usage);
System.exit(1);
} else if (CLIError) {
System.err.println(“Invalid/illegal switches encountered\n”);
System.err.println(“Usage: ” + usage);
System.exit(2);
}

// extract the input args
String className = args[firstArgOff].trim();
wc.classPath = args[firstArgOff + 1].trim();

// make sure the class name ends with a “.class”
if (!className.endsWith(“.class”)) {
//System.err.println(thisMethod + “the classname should be specified with a .class suffix, adding…”);
className = className + “.class”;
}
// create instances of the name in DOS and UNIX format
wc.dosName = className.replace(‘/’, ‘\\’);
wc.unixName = className.replace(‘\\’, ‘/’);

if (wc.verboseLevel > 0) {
System.err.println(thisMethod + “searching for class: ” + className);
System.err.println(“\tDOS format:  ” + wc.dosName);
System.err.println(“\tUNIX format: ” + wc.unixName);
if (wc.verboseLevel == 1) {
System.err.println(thisMethod + “within classpath:”);
StringTokenizer st = new StringTokenizer(wc.classPath, wc.pathSeparator);

while (st.hasMoreTokens()) {
System.err.println(“\t” + st.nextToken());
}
}
}

wc.locateClass();

String fl = new String(wc.getFoundList());
if (fl != null) {
if (wc.verboseLevel == 1) {
System.err.println(thisMethod + wc.unixName + ” found in:”);
}
StringTokenizer flToken = new StringTokenizer(fl, wc.pathSeparator);
while (flToken.hasMoreTokens()) {
System.out.println(flToken.nextToken());
}
}
}
/**
* returns the verbose level setting value
* @param newVerboseLevel int
*/
public void setVerboseLevel(int newVerboseLevel) {
verboseLevel = newVerboseLevel;
}
}

Update regarding Palm Pre

February 7, 2010

Friends and co-workers have been complaining that I have not been updating my blog. So, after a 3 month hiatus, here’s an update regarding the Pre…

As a long time (decades old) Palm user, my advise is don’t buy one.

PalmPreSprintNav

October 11, 2009

I recently (7 days ago) bought a Palm Pre. Part of the package (on the Sprint Network) is the Sprint Navigation (SN) utility. I figured, as my first (hopefully) useful blog on Word Press, I’d detail my first-time experience with Sprint Navigation. I’ll cover the pros and cons of the Pre at some later point. What I wont be doing here is covering what everyone else has said already – although there is some overlap.

Background: Sprint Navigation is their turn-by-turn GPS tool for the Pre. As such, it turns your phone into an on-demand GPS. While I am all for convergence to a single device for most applications, I will admit that am dubious about using my phone for a turn-by-turn GPS. Reason being that driving in heavy traffic in an unknown city makes you kind of reliant on your GPS. It doesn’t help when the GPS changes flavor periodically from a GPS footprint to a phone, schedule reminder, email notifier, etc. That said; here is my first time experience:

I used Pre/SN to aid my commute home this evening. Actually, I programmed it to take me to a Best Buy and then home. Along the way I purposely diverted to different routes to see how the Pre/SN deals with the diversion. I also made a few phone calls and checked email – kids: don’t try this at home. Basically I spent way too much time focusing on my device and not enough on the road.

Last comment before getting to the good stuff. I should point out that I have a Garmin Nuvi 600 or something like that. Not the newest, but not that old. It is inevitable that I compare the Pre/SN to the Nuvi. I’ve also rented several cars over the years with Hertz’s Ever Lost (err, Never Lost). So I have that to fall back on too.

Regardless; some interesting things happened on this first-outing with the Pre/SN:

1. Nag, nag, nag. First thing that became apparent within the first mile of travel was the nagging nature of Pre/SN vs the Nuvi. The Nuvi talks fairly infrequently. The Pre/SN, on the other hand, talks way too much. There are 3 bends in the road in the first mile of my commute. Nuvi totally ignores them. The Pre/SN, on the other hand, tells me about each and every one: “Slight Right”, “Slight Left”. I guess it’s OK and, had it been my first GPS experience, I would not think twice. I just found it fairly annoying. Just tell me when to turn, I will keep the Tahoe between the lines – unless there is a hug puddle in the road, then it’s splash city, but I digress.
2. Small Screen vs 1 device – One problem that the Pre can’t overcome is the screen is small. I’ve grown use to the ample display of my Nuvi. BUT BUT BUT, dragging my Nuvi with me on business trips (which I’ve done often) is a huge hassle. Having the phone as a GPS would mean one less thing to drag with me. Alternatively, I’ve almost left my GPS in the car because I was in a rush to catch a plane. The only thing worse than losing your GSP on a trip is losing your cell phone and only link to the outside world.  So the small screen is a knock against the Pre.  Losing your cell phone or GPS because you are in a rush is just a fact of life.
3. No Mount – Now I can easily resolve this problem, but I had no good way to standup the Pre on my dash. I did lean it up against the windshield while in the parking lot and sit back in the driver’s seat. The impression I got was that the screen would be too small and too far away to get a good spacial understanding of an intersection under severe traffic conditions, but I don’t know this for sure. Aside about the Nuvi: My dash mount broke a long time ago. Since then, I’ve found you can wedge it in the corner of the dash – right under the inspection sticker. It never budges and is in a difficult spot for thieves to notice. This is totally a function of the dash/windshield geometry on a Tahoe. Now back to our story….
4. Volume – I’m not going to say too much about this because I’ve seen it blogged about on other sites. Other than to say: my experience fell into the “volume was too low” camp. I would have appreciated twice or, at least, 50% more volume.
5. Like the Nuvi, when you decide to take a different highway from the one prescribed in the plan, it gets all kinds of hysterical… attempting to reroute you back to the road that you purposely missed…. and that’s perfectly OK. After all, in a strange location you might have missed it by accident. What shocked the heck out of me was that, at one point, it instructed me to commit a U-turn on a two lane (one in each direction) high-speed parkway. Yikes! It scares me to think how that would have turned out given the traffic – not to mention it would have been illegal. I’ve never had the Nuvi do that. To its credit the Nuvi always tries to get me to NJ-jug-handle myself back on track by committing a series of right turns. I do not recall the Nuvi EVER telling me to make a U-Turn.  In fact, I’m surprised the few times it tells me to loop around by making a left.
6. At one point it seemed that the Pre/SN gave me vague reference as to which entrance ramp to use. It only told me (something like) “slight right ahead to Rt27”. At the time I was less than 100′ before the west entrance, but it was the, further, east entrance that I was shooting for. Had I not known that, I would have been tempted to jerk the truck onto the west entrance. I’ll have to retry this on the same stretch of road sometime and pay more attention.
7. At one point I entered a limited-access-highway – one with service roads that ran parallel for the entire length. No sooner had I entered than the Pre/SN instructed me to take the next exit (putting me back on to the service road). I opted not to take this diversion (mainly because of the traffic light situation). That said, like the Nuvi, the GPS was unable to differentiate between me being in the high-speed-right-lane vs the service-road-left-lane… so, basically, it though I took the service road. Note: this is a GPS resolution limitation – not a reflection on any GPS device. At the next entrance, it suggested I get back on. That was a very odd experience. I have no idea why it would do this. I could see if there was a traffic alert on the high-speed side, by it was clear (well as clear as it gets here on Long Island at rush hour).

Now my experiment takes a weird twist – one that I am not sure anyone else has blogged about….

Next (after parking – I’ve caused enough close calls on the road today) I turned on my Nuvi and enabled Blue Tooth on the Pre. I typically used the Nuvi as my hands-free speakerphone for my Palm 755p. I’ve been doing the same with the Pre – well for the 7 days I’ve had it so far.

So lets stop and think about this: I am using the Pre (with the aid of Sprint navigation) as a GPS and the Nuvi (a well endowed GPS in its own right) as a speaker phone. I will admit that that is just plan wrong on several levels, but it did lead to some interesting situations…

1. First, the BT worked as expected. My voice prompts were transferred to the Nuvi. In the process this totally resolved my low-volume issues. Which tells me that, like I read in other blogs, that adding a BT hands free will resolve this problem.
2. I then made a call and, as expected, the voice commands to the Nuvi stopped – in favor of letting me talk on the phone. They stopped in total. The Pre was smart enough to not try to talk over me while I was on the phone. I was curious if they would pickup on the Pre while I was on the call. That would be both good and bad. I should point out this is the same user-experience I get when using my Treo with the Nuvi. When I am on a call, the Nuvi stops announcing directions. After I disconnect, it picks back up. In both cases, the map stays active – just no voice output.
3. Here is a strange part: after I disconnected from my call, the Pre started announcing turns – NOT THE NUVI. It’s like the BT session was broken by the call and not reconnected again afterwards. NOTE: now maybe this is a function of how the BT standard is supposed to work in this situation. If so, I’m sure someone will inform me via my blog. I tried (AGAIN DONT DO THIS AT HOME -I almost killed myself due to driver inattention!!!) turning off BT on the Pre and then starting it back up. It would not reconnect to the Nuvi. I tried turning the Nuvi off and on – same thing. The only solution was to terminate the trip and, effectively, start from scratch. What was most odd was, if it dropped the BT session, why did it not start giving me turn directions while I was on the phone. If it was cognizant that my phone call ended (and it was because that’s when the voice prompts started) why not switch back to the Nuvi’s speaker phone. Again, odd behavior. I don’t know who’s to blame here. It could easily be the Nuvi with its (possibly) dated BT specification.
4. Switching devices – Note: I have no idea how this next magical thing happened. It was so surprising, I almost drove into a parked car. I was using the Pre to get directions to a local friend’s house – again using the Nuvi as a speaker phone. In this case, I used the Pre to lookup my friend’s address via my contacts. At some point I accidently hit a <magic> key on the Nuvi (which I had laying on my center console (note to self: clean up the interior – it’s a mess). The next thing I know the Nuvi has calculated the route and is dictating the directions – the voices are different + I could see the map was activated and tracking on the Nuvi while the Pre had given up. I can only imaging that the Pre had transferred the destination to the Nuvi when I hit the magical key. Like I said, it was freaky enough that while I was staring at the devices trying to figure out what just happened a parked car came up out of nowhere and almost hit me. Damn, parked car. Watch it the next time.

Conclusion:

1. They really need to fix the volume issue. Relying on an external BT speakerphone is fine, but I expect better given the cost of the device. At the end of the day the Pre should be able to stand on its own.
2. My experiences might be somewhat unique in that I used another GPS as my hands-free device. So take this into account when reading this post.
3. I didn’t like the excessive output from the Pre. I don’t want it to drive for me, just tell me when to make the major turns. If they add micro-thruster to the device, I guess I could strap it to the steering wheel and let it drive for me, but, until then, STOP TALKING SO MUCH for crying out loud!
4. I’m still undecided if I like having my phone also act as a GPS. I don’t think it would work out well if I’m tired and trying to drive to my hotel after a 5 hr flight in a totally new city with significant traffic, daylight fading and my GPS decides to become something else – even momentarily. This is not a criticism of the Pre. It’s a convergence issue when one of the devices you are attempting to converge is mission-critical. Right? You don’t share the CPU for the fuel rod monitor app with the coffee pot timer app. I could easily see an auto version of the Pepsi Syndrome.
5. On the bright side, it did a fairly good job of getting me to my destination. It made some out-right bad suggestions (u-turn) and inefficient suggestions (getting on-to the service road), but I’m a big boy. I always take that inputs as “this is only a suggestion you do whatever you have to to keep it safe”. Kind-of-like talking to ATC during a landing. Yeah, they are telling you where to go, but you don’t take those instructions so literally that you smite the bottom of the plane with the ground.
6. Messing with the phone and hands free was just a scary, stupid thing to do. I won’t be redoing this type of test again for a long time – if ever.

All in all the Pre did a fine job as a GPS – given that is not its main focus in life. Since I typically have my phone with me, it’s good to know I can use it in a pinch as a GPS. All things considered thought, I won’t be checking my Nuvi out the driver’s window any time soon.

I’m back!

October 10, 2009

Sorry, it’s been a while since I abruptly left my blog at Sun. Lesson well learned, don’t rely on a corporate blog. Well, here’s to a new blog space.