Saturday, January 21, 2012

Download all of your images from Smugmug

I cheated and used wget to grab the files. This could be done using a perl module if you wanted.

You will need to have the WWW::SmugMug::API module installed for this script to work. All of the others should be standard stuff.




#!/opt/bin/perl

use warnings;
use strict;
use Data::Dumper;
use WWW::SmugMug::API;
use File::Path;

my $APIKey='your_key';
my $username='your_login_email';
my $password='your_password';

my $dest_folder='/share/jgarland/Photos/Smugmug';

my $sm_api = WWW::SmugMug::API->new(
 {
  sm_api_key => $APIKey,
  secure     => 0
 });

$sm_api->login_withPassword(
 {
  EmailAddress => $username,
  Password     => $password
 });

&get_images;

$sm_api->logout;
exit;





sub get_images {

 my $albums=$sm_api->albums_get();
 foreach my $album (@{$albums->{'Albums'}}) {
  my $images=$sm_api->images_get(
   {
    AlbumID => $album->{'id'},
    AlbumKey => $album->{'Key'}
   });
  foreach my $image (@{$images->{'Images'}}) {
   my $image_info=$sm_api->images_getInfo(
    {
     ImageID => $image->{'id'},
     ImageKey => $image->{'key'}
    });
   download($album, $image_info);
  }
 }
}


sub download {
 my $album=shift;
 my $image_info=shift;
 my $album_folder=$dest_folder . '/' . $album->{'Category'}->{'Name'} . '/' . $album->{'Title'};
 my $image_file=$album_folder . '/' . $image_info->{'Image'}->{'FileName'};

 unless(-d $album_folder) { mkpath $album_folder or die; }

 if ( -e $image_file ) { return(); }
 
 my $command='/usr/bin/wget -c -q \'' . $image_info->{'Image'}->{'OriginalURL'} . '\' -O "' . $image_file . '"';
 print "$command\n";
 my @results=`$command`;
 my $errlvl=$?;
 print Dumper(@results);
 if ( $errlvl == 0 ) {
  return();
 } else {
  unlink($image_file);
  die("errlvl=$errlvl\nDeleting $image_file\n");
 }

}

Thursday, October 13, 2011

What do I do with this core file?

Use this script to generate a useful backtrace from the core file.

#!/bin/bash

corefile=$1
outfile=$1.gdbtrace.log

function getprocess {

        commandstring=$(gdb -c $corefile \
                --eval-command='set pagination off' \
                --eval-command='bt' \
                --eval-command='quit' \
                |awk '/Core was generated by/ { split($0, a, "`"); split(a[2], b, "'\''"); split(b[1], c, " "); print c[1] }')

        echo $commandstring|awk '{print $1}'
}


if [ -a $corefile ] ; then
        process=$(getprocess)
else
        echo You must provide a core file as an argument
        exit
fi

if [ -a $process ] ; then

echo Core was generated by $process

gdb $process \
                -c $corefile \
                --eval-command='set pagination off' \
                --eval-command="set logging file $outfile" \
                --eval-command='set logging on' \
                --eval-command='bt' \
                --eval-command='bt full' \
                --eval-command='thread apply all bt' \
                --eval-command='thread apply all bt full' \
                --eval-command='quit'

echo "Trace written to $outfile"

else
        echo "Can not find $process. This script my be broken, or the file disappeared."
        exit
fi

Tuesday, March 22, 2011

German exit signs

I've made my way to Frankfurt, Germany. Tomorrow I will be taking the train to Regensburg. I will post all of my photos on my photo sharing site later here.

All throughout the airport I've seen these exit signs and they reminded me of the signs you see inside the game Portal.

Here is a picture of one of the signs. (I didn't take this picture. I can't get my memory card reader to work right now.)


And here is a logo for the game:

Tuesday, June 08, 2010

Yamaha V6 Outdrive stuck shifter repair

Here are some pictures and directions for repairing a stuck shifter on a Yamaha outdrive that I created about two years ago for my Yamaha Sterndrive owner's group. This is a common problem with this unit.

Wednesday, May 19, 2010

80's / Zombie party

So we had this 80's Zombie party at our place last weekend. I was going to be Zombie Mario, but I gave up on the Zombie makeup after screwing it up several times. So I was just Mario the Zombie slayer.

Anyways... I had one of my friends film me playing Mario Brothers on the Wii. It cracks me up every time I watch it. Check it out:



I should also mention that my wife made an awesome brain cake for all the zombies to munch on:

Twittering doorbell

All I wanted was a doorbell that would send me a text message when somebody rang it, and I wanted it NOW. There are a number of ways I could have done this. Ideally I would have used an opto isoloator, but Radioshack didn't have those. They did have a full wave bridge rectifier, and a 5V relay. I already had some random capacitors, and a 5V regulator, so that would have to do. I connected the AC inputs on the rectifier inline with the doorbell using the connections behind the doorbell transformer in my garage. The relay switch is connected to the digital input and ground connections on my IOBridge. I've configured the iobridge to send an email to both my magic account at ping.fm that updates twitter, as well as an email distribution list that sends text messages to both my wife and myself, as well as to our email inboxes.

You can find the twitter updates from my doorbell on my twitter account here: http://twitter.com/jgarland79

Here is the schematic and a photo:





Sunday, May 09, 2010

Busting the myth: Unbalanced Breaker panel = Larger electric bill

There is a myth that if your breaker panel is "unbalanced" then you will be billed for the higher leg on the meter.

Let's find out...






I didn't film the third part because it was dark outside, but I went outdoors and monitored the meter before and after I shut off the breakers on one of the phases making the load unbalanced. The meter DID spin half as fast, so this proves that the meter IS accurate and this myth is BUSTED!

DHCP Notify Parsing with Polycom phones

Syslog sample:

Jul  8 18:25:12 babelfish dhcpd: {"vendor-class-identifier": {"substrings": [ {"company": "Polycom"}, {"part": "SoundPointIP-SPIP_430"}, {"part_number": "2345-11402-001,1"}, {"app_version": "SIP/2.2.2.0084/20-Nov-07 10:17"}, {"bootrom_version": "BR/4.1.0.0219/10-Dec-07 13:08"} ] }}

create polycom.conf and include it in your dhcpd.conf file.

authoritative;
allow booting;
 
option option-150 code 150 = text;
option option-155 code 155 = text;
option option-160 code 160 = text;
option sip-server code 151 = text;
option voice-vlan code 128 = text;
 
 
class "polycom" {
            match if(
            (substring (option vendor-class-identifier, 0, 4) = 00:00:36:3d) and
            (substring (hardware, 1, 12) = 00:04:f2:11:f3:b9)
                        );
 
            set vendor_class_identifier = (substring (option vendor-class-identifier,5,(extract-int ((substring (option vendor-class-identifier, 4, 1)),8))));
            set vendor_class_identifier_1_len = (extract-int ((substring (vendor_class_identifier,1,1)),8));
            set vendor_class_identifier_1 = (substring (vendor_class_identifier,2,vendor_class_identifier_1_len));
 
            set vendor_class_identifier_2_len = (extract-int ((substring (vendor_class_identifier,(3 + vendor_class_identifier_1_len),1)),8));
            set vendor_class_identifier_2 = (substring (vendor_class_identifier,(4 + vendor_class_identifier_1_len),vendor_class_identifier_2_len));
 
            set vendor_class_identifier_3_len = (extract-int ((substring (vendor_class_identifier,(5 + vendor_class_identifier_1_len + vendor_class_identifier_2_len),1)),8));
            set vendor_class_identifier_3 = (substring (vendor_class_identifier,(6 + vendor_class_identifier_1_len +  vendor_class_identifier_2_len),vendor_class_identifier_3_len));
 
            set vendor_class_identifier_4_len = (extract-int ((substring (vendor_class_identifier,(7 + vendor_class_identifier_1_len + vendor_class_identifier_2_len + vendor_class_identifier_3_len),1)),8));
            set vendor_class_identifier_4 = (substring (vendor_class_identifier,(8 + vendor_class_identifier_1_len +  vendor_class_identifier_2_len + vendor_class_identifier_3_len),vendor_class_identifier_4_len));
 
            set vendor_class_identifier_5_len = (extract-int ((substring (vendor_class_identifier,(9 + vendor_class_identifier_1_len + vendor_class_identifier_2_len + vendor_class_identifier_3_len + vendor_class_identifier_4_len),1)),8));
            set vendor_class_identifier_5 = (substring (vendor_class_identifier,(10 + vendor_class_identifier_1_len +  vendor_class_identifier_2_len + vendor_class_identifier_3_len + vendor_class_identifier_4_len),vendor_class_identifier_5_len));
 
 
            log(info, (concat ("{\"vendor-class-identifier\": {\"substrings\": [ {\"company\": \"", vendor_class_identifier_1,"\"}, {\"part\": \"", vendor_class_identifier_2,"\"}, {\"part_number\": \"", vendor_class_identifier_3,"\"}, {\"app_version\": \"", vendor_class_identifier_4,"\"}, {\"bootrom_version\": \"", vendor_class_identifier_5,"\"} ] }}")));
 
            if (option dhcp-message-type = 8)
            {
                        option dhcp-parameter-request-list 2,3,4,6,15,17,42,43,60,66,128,150,151,155,160;
                        option option-150 "http://PlcmSpIp:PlcmSpIp@172.16.129.94/polycom/";
                        option option-155 "http://PlcmSpIp:PlcmSpIp@172.16.129.94/polycom/";
                        option option-160 "http://PlcmSpIp:PlcmSpIp@172.16.129.94/polycom/";
                        option tftp-server-name "http://PlcmSpIpFOO:PlcmSpIp@172.16.129.94/polycom/";
                        option sip-server "sip.voip.local";
                        option domain-name-servers 172.16.129.94, 172.16.129.94, 172.16.129.94, 172.16.129.94;
                        option domain-name "voip.local";
                        option ntp-servers 172.16.129.94;
                        option time-servers 172.16.129.94;
                        option time-offset -18000;
                        #option voice-vlan "VLAN-A=10;";
            }
}
 
subnet 172.16.0.0 netmask 255.255.0.0 {
}

Thursday, January 14, 2010

Twitter update your energy usage using a TED 5000

The Energy Detective 5000 has an API that can be polled for data using this simple perl script that I wrote.

You can find my Twitter feed here: http://twitter.com/jgarland79power

Order your own TED 5000 here.

If you are running Debian Linux you will need to install a few dependencies:
sudo apt-get install libxml-simple-perl libwww-curl-perl

And you can automate the execution of this script with an hourly cron job:
Run: crontab -e
and then add this line (assuming you put my script in ~/bin/:
0 * * * * ~/bin/twitterpower.pl

#!/usr/bin/perl

# Written by Jason Garland @ http://blog.jasongarland.com/

my $twitter_user="jgarland79power";
my $twitter_password="super_secret_password";

my $ted_ip="192.168.3.132";

# use module
use XML::Simple;
#use Data::Dumper;
use WWW::Curl::Easy;

sub write_callback {
 my ($chunk,$variable)=@_;
 # store each chunk/line separately
 # This should be faster than using $$varable .= $chunk;
 push @{$variable}, $chunk;
 return length($chunk);
}

my $curl = WWW::Curl::Easy->new();

my @body;
$curl->setopt(CURLOPT_WRITEFUNCTION, \&write_callback);
$curl->setopt(CURLOPT_FILE, \@body);
$curl->setopt(CURLOPT_URL, "http://$ted_ip/api/LiveData.xml");
$curl->perform;
my $body=join("",@body);

# create object
$xml = new XML::Simple;

# parse XML
$data = $xml->XMLin($body);

my $PowerTDY=$data->{Power}->{Total}->{PowerTDY};

$status="used $PowerTDY watt hours of #electricity since midnight today. Find out more here: http://a1.ly/7";

print $status,"\n";
$curl->setopt(CURLOPT_URL, "http://twitter.com/statuses/update.json" );
$curl->setopt(CURLOPT_POST, 1 );
$curl->setopt(CURLOPT_POSTFIELDS, "status=$status" );
$curl->setopt(CURLOPT_USERPWD, "$twitter_user:$twitter_password" );
$curl->perform;

Friday, July 20, 2007

Use a GPS with your iPhone

Here is a little trick to allow you to use a GPS feed with Google Maps on your iPhone.

The Google Maps app on the iPhone is similar to the Google Maps for Mobile. A while back I discovered that you would input a URL for a KML feed into Google Maps mobile so when I got my iPhone I gave it a try on there too AND IT WORKED!

Simply type in the URL for a KML feed into the search box on the Google Maps app on your iPhone.

So how do we get our current GPS cords into the iPhone? You use a separate device like the Motorola i415 that you can pick up at Walmart for ~ $30 and load up the mologogo.com application on it. The phone can then transmit your coordinates to a web server where you can generate a KML feed for your iPhone.

You can find sample scripts on how to build the KML feed here: http://mologogo.wikispaces.com/

Here is the feed for mine: http://gps.jasongarland.com/earth1.kml

Type it into the search box on your iPhone and you will see my current location. (Assuming I have the Mologogo app running)

NO STALKERS PLEASE! This means don't attempt to go to any of the locations on this map to try and find me. If you want to talk to me you can send me a message on this blog.