Archive for the ‘hacks’ Category

What to do when iTunes hoses your USB port

Friday, May 2nd, 2008

For whatever reason, iTunes sometimes just screws up the the USB device I plug my iPod into. It’s toast, and no device will work; not the iPod, not a flash drive, nothing. No amount of being careful with iTunes and “ejecting” the iPod will help.

Rebooting the computer fixes it, but this happens with such regularity I’d be rebooting several times a day.

But I discovered that if you disable the USB port/device, and then enable it again, the problem is also fixed. Going through the device management dialogs is incredibly cumbersome, so I wrote a script.

fixusb.bat:

@echo off
echo "disabling usb device..."
devcon disable "@USB\VID_0424&PID_2504\5&18F4DAC0&0&5"
echo.
echo "enabling usb device..."
devcon enable "@USB\VID_0424&PID_2504\5&18F4DAC0&0&5"
echo.
pause

The @USB\VID_... bit is the USB device ID. To get the device ID, you’ll have to go to the Device Manager dialog. Figure out which device the iPod is attached to (I don’t remember exactly how I did this; sorry). Then on the “Details” tab of the device “Properties” dialog you can get the “Device Instance Id”.

I have to use this all the time, so put a shortcut to it on the desktop.

Presta inflator on the cheap

Thursday, April 10th, 2008

One of the best things I got from my brother when he moved out of his huge house into a small apartment was his compressor. It’s amazing how useful air is.

So most bike tires these days have presta valves, which are not nearly so easy to deal with as schraeder valves like those on cars. There are adapters that sort of convert presta to schraeder, but they’re kind of a cumbersome, and I wanted something more convenient. Surfing around, I found a tool that does it commercially available for $50.

But since I already have a blower tool, and I’m terminally cheap, I decided to try build one for less.

Voila:
5.jpg

And just screwing around a little, I turned it into an Instructable.

Custom iPod Touch icon

Friday, January 18th, 2008

Thanks to a post over at Laughing Squid, bookmark MrBalky on your iPod Touch (or the less cool iPhone) and revel in the awesomeness:

itouch

Of course, everyone is doing it.

The TiVo widget

Wednesday, January 2nd, 2008

The TiVo now playing list has been a “feature” on the right-hand side of this blog for a couple years now.

Todd has been admiring it for his blog for some time, but the poor fellow only had Series 3 TiVos, which had networking features turned off so he couldn’t do the same. Now that TiVo has seen fit to turn that feature on in the S3s, I found I had to clean up the code so he could use it over on his blog.

As Todd says, sometimes you have to build things just because you can.

SAC alert “application”

Tuesday, December 18th, 2007

During the recovery from my previously mentioned osteotomy, I’ve been spending lots of time chatting with my physical therapist Larry Meyer. He’s an interesting and personable guy (and is really handling my PT well). In my dozens of appointments, we’ve talked about lots of stuff, including Lijit, Christmas presents, and something near and very dear to me, bargain hunting.

Along the way, I mentioned Steep & Cheap, which is basically like the woot of outdoor gear. They have single deal after single deal, about every 20 minutes or so, all day long. It’s fine for me because I work at a computer all day long and can see each deal as soon as it is posted. But Larry is not at a computer, though he does have access to one.

What Larry does have, though, is a pager with an email address. It got me to thinking, so I hacked together a little PHP code, mixed it gently with cygwin cron, to poll the SAC deal feed. If the deal changes, the application will send him a page.

So far, he’s not tired of the constant buzzing on his hip.

Here it is. Standard disclaimer applies: this is quick n’ dirty(tm):

<?
// Requires PEAR::Mail
require_once( 'Mail.php' );

$sac_rss = "http://www.steepandcheap.com/steepcheap/rss.xml";
$item_element = "ITEM";
$have_item = FALSE;
$in_item = FALSE;
$current_element = "";
$message = "";
$statusFile = "sacdeal.txt";

$to_list = array( "pager_email_address" );

$from = 'SAC Alert <sacalert@my.hosting.company>';
$subject = 'SAC deal alert';

$host = 'smtp.server.name';
$username = 'smtp.userid';
$password = 'smtp.password';

$to = "";
foreach( $to_list as $emailaddy )
{
  $to .= "$emailaddy, ";
}
echo "$to\\n";

function startElement( $parser, $name, $attrs )
{
  global $current_element, $have_item, $in_item, $item_element;
  $current_element = $name;
  if ( $name == $item_element )
    $in_item = TRUE;
}

function endElement( $parser, $name )
{
  global $current_element, $have_item, $in_item, $item_element;
  $current_element = "";
  if ( $name == $item_element )
  {
    $in_item = FALSE;
    $have_item = TRUE;
  }
}

function elementData( $parser, $text )
{
  global $current_element, $have_item, $in_item, $message;
  if ( $in_item && !$have_item )
  {
    // the message content is only the title or the price
    if ( $current_element == "TITLE" || $current_element == "SAC:PRICE" )
      $message .= "$text\\n";
  }
}

$xml_parser = xml_parser_create();
xml_set_element_handler( $xml_parser, "startElement", "endElement" );
xml_set_character_data_handler( $xml_parser, "elementData" );

// fetch the feed content and parse it
$xml = file_get_contents( $sac_rss );
xml_parse( $xml_parser, $xml );
xml_parser_free($xml_parser);

// compare the current item in the feed to the last one we sent email about
$oldcontents = file_get_contents( $statusFile );
if ( $oldcontents != $message )
{
  $headers = array( 'From' => $from,
                    'To' => $to,
                    'Subject' => $subject );

  $smtpParams = array( 'host' => $host,
                       'auth' => true,
                       'username' => $username,
                       'password' => $password );

  $smtp = Mail::factory( 'smtp', $smtpParams );

  $mail = $smtp->send( $to, $headers, $message );

  echo $message;
  if (PEAR::isError($mail))
  {
    echo( $mail->getMessage() . "\\n" );
  }
  else
  {
    echo( "Message successfully sent!\\n" );
    file_put_contents( $statusFile, $message );
  }
}
else
{
  echo "same deal as last time\\n";
}
?>

Blinklist -> del.icio.us

Friday, December 7th, 2007

Long ago I migrated from del.icio.us to Blinklist. Why? Blinklist would let me combine tags when trying to find a link, and del.icio.us wouldn’t. For example, with Blinklist I could find a link tagged with both “reference” AND “css”. On del.icio.us, only “reference” OR “css”.

Unfortunately, Blinklist dropped that feature a while back. I just noticed del.icio.us added it, and I’m tired of waiting for Blinklist to add it back in.

But I faced the problem of getting all my bookmarks from Blinklist back to del.icio.us. Probably such a tool exists already, but it was pretty easy to hack together in PHP.

Download your Blinklist bookmarks in XML from http://www.blinklist.com/?Action=User/Export/export.php and save them in blinklist.xml.

Blinklist allowed spaces in tags, del.icio.us does not. The code converts spaces in the tags to hyphens. PEAR HTTP_Request and openssl is required in your PHP install.

Run it from the command line: php blinklist-to-delicious.php blinklist.xml

Here’s the code. Standard disclaimer applies: this is quick n’ dirty(tm):

<?php
/* Take blinklist bookmarks xml
             and add them to del.icio.us via the API.

---------------------------------------------------
del.icio.us API:

https://api.del.icio.us/v1/posts/add?

&url (required) - the url of the item.
&description (required) - the description of the item.
&extended (optional) - notes for the item.
&tags (optional) - tags for the item (space delimited).
&dt (optional) - datestamp (format "CCYY-MM-DDThh:mm:ssZ").
&replace=no (optional) - don't replace bookmark if already posted.
&shared=no (optional) - make the item private

---------------------------------------------
Blinklist entry XML:
  <item>
   <title>MrBalky Heavy Industries</title>
   <description></description>
   <link>http://www.mrbalky.com</link>
   <guid></guid>
   <pubDate>1197042355</pubDate>
   <private></private>
   <favourite></favourite>
   <vote>0</vote>
   <category>awesome,cool,stupid</category>
  </item>
*/
require_once "HTTP/Request.php";

$delicious_id = 'mydeliciousid';
$delicious_pass = 'mypassword';

define( "ITEM", "ITEM" );
define( "TITLE", "TITLE" );
define( "LINK", "LINK" );
define( "PUBDATE", "PUBDATE" );
define( "CATEGORY", "CATEGORY" );

$item = array();
$have_item = FALSE;
$in_item = FALSE;

function startElement( $parser, $name, $attrs )
{
  global $current_element, $in_item, $item;

  $current_element = $name;
  if ( $name == ITEM )
  {
    $item = array();
    $in_item = TRUE;
  }
}

function endElement( $parser, $name )
{
  global $current_element, $in_item, $item;

  $current_element = "";
  if ( $name == ITEM )
  {
    $in_item = FALSE;
    addToDelIcioUs();
  }
}

function elementData( $parser, $text )
{
  global $current_element, $in_item, $item;

  if ( $in_item )
  {
    $item[ $current_element ] .= $text;
  }
}

function addToDelIcioUs()
{
  global $item, $delicious_id, $delicious_pass;

  $itemURL = urlencode( $item[LINK] );
  $itemTitle = urlencode( $item[TITLE] );
  $itemDate = strftime( '%Y-%m-%dT%H:%M:%SZ', $item[ PUBDATE ] ); 

  $apiURL = "https://api.del.icio.us/v1/posts/add?url=$itemURL";
  $apiURL .= "&description=$itemTitle";
  $apiURL .= "&dt=$itemDate";
  $apiURL .= '&tags=';
  $sep = "";

  $itemTags = split( ',', $item[ CATEGORY ] );
  foreach( $itemTags as $tag )
  {
    $tag = str_replace( ' ', '-', $tag );
    $apiURL .= "$sep$tag";
    $sep = '+';
  }
  echo "$apiURL\\n";

  $req =& new HTTP_Request( $apiURL );
  $req->setBasicAuth( $delicious_id, $delicious_pass );

  $response = $req->sendRequest();

  if ( PEAR::isError($response) )
  {
    echo 'Error: '.$response->getMessage()."\\n";
  }
  else
  {
    echo 'Response: '.$req->getResponseBody()."\\n";
  }

  echo "\\n";

  sleep( 5 );  // be polite to del.icio.us
}

$inputFile = $argv[1];
echo "input: $inputFile\\n";
$xml = file_get_contents( $inputFile );
$xml_parser = xml_parser_create();
xml_set_element_handler( $xml_parser, "startElement", "endElement" );
xml_set_character_data_handler( $xml_parser, "elementData" );
xml_parse( $xml_parser, $xml );
xml_parser_free($xml_parser);
?>

A TiVo post

Wednesday, April 4th, 2007

This is a post about TiVo. “TiVo” is a favorite search term at Lijit, so I’m writing a post about it so TiVo will come up in my search results.

You can see what’s currently recorded on my TiVo in the sidebar on the right.

tivo logo