hmmm....

The Often Overlooked Perl Module Pod::Usage

Pod::Usage is one of those boring modules that doesn’t get the attention it deserves. Included in Perl core since 5.6.0, released fourteen years ago, it’s not a new kid on the block. It’s job isn’t sexy, so not lots of talks, blog posts, or tweets about it. There are only 5 ++s for the distribution on metacpan.org. It’s my goto module for all but the most trivial scripts, I probably use it second to only pragmas in scripts. (Haha, I made a funny.)

Pod::Usage generates usage/help output for your scripts by extracting relevant bits from your POD. This means you write usage/help information once for the POD and you get both your man page and -h command line help. Let’s look at its usage by starting with the result. I’ll use otfile, a simple script for serving a file via HTTP from the command line for these examples.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ otfile -h
Usage:
    $ otfile [-a -p 1234] <file to serve>

Options:
    --auto or -a
            Auto port selection. Increments specified port until successful.

    --port=N or -p N
            Use specified port, defaults to 1234.

    --multiple or -m
            Don't exit after serving the file the first time. To serve a
            file to multiple people. Requires, CTL+C to exit.

    --help or -h
            this help information

$

Nothing exceptional here, this is the style and content you would expect from any script on a POSIX like system. We get similarly unsurprising output for incorrect arguments.

1
2
3
4
5
6
$ otfile --invalid-arg-named-yaakov
Unknown option: invalid-arg-named-yaakov
Usage:
    $ otfile [-a -p 1234] <file to serve>

$

So what does the source look like? One of Pod::Usage’s benefits is the simplicity in using it.

1
2
3
4
use Pod::Usage;
use Getopt::Long;

GetOptions( ..., 'help' => sub { pod2usage(1) } ) or pod2usage(2);

That’s it in terms of code! You can substitute Getopt::Std or your other argument parser of choice just as easily. This was really cheating though since the real meat of it is in the POD. So anything special there?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
=head1 SYNOPSIS

$ otfile [-a -p 1234] <file to serve>

=head1 OPTIONS

=over 8

=item B<--auto> or B<-a>

Auto port selection.  Increments specified port until successful.

=item B<--port=N> or B<-p N>

Use specified port, defaults to 1234.

=item B<--multiple> or B<-m>

Don't exit after serving the file the first time. To serve a file to multiple
people. Requires, CTL+C to exit.

=item B<--help> or B<-h>

this help information

=back

Nothing special in the POD. Pod::Usage with the source I used outputs either the POD’s SYNOPSIS section or the SYNOPSIS section and any section titled OPTIONS, ARGUMENTS or OPTIONS AND ARGUMENTS.

That’s it! Now, head over to Pod-Usage on metacpan.org and give it some ++ love.

Logging Apple Battery Data With Perl

Inspired by a blog post and the code that goes with it at jradavenport/batlog, I created a perl script for logging Apple laptop battery details last August.

My script logs 11 values using ~67 bytes per record. The oldest log I have begins 288 days ago and is 17,122,966 bytes for an average of 59.4 KB/day or 21 MB/year. The log is missing data points due to things like prolonged hibernation or sleep, theoretical max is around 35MB/year with 10 minute resolution.

The repo is on GitHub.

Sample Graphs

A simple gnuplot script is included in the repo which produces the below graphs.

A couple days of output: Sample Battery Graph

9 months of output: Sample Battery Graph 9 Months

Things get a bit squashed at 9 months but the most interesting value over long durations, battery health, is clearly visible.

The Code

Acquiring the data for this in Perl is exceedingly simple. Apple provides a binary called ioreg for interacting with the I/O Kit Registry. Asking for battery information with the arguments -rc AppleSmartBattery gets us almost JSON:

1
2
3
4
5
6
7
8
9
+-o AppleSmartBattery  <class AppleSmartBattery, id 0x100000203, registered, matched, active, busy 0 (0 ms), ret$
    {
      "TimeRemaining" = 36
      "AvgTimeToEmpty" = 65535
      "InstantTimeToEmpty" = 65535
      "ExternalChargeCapable" = Yes
      "FullPathUpdated" = 1401701615
      "CellVoltage" = (4193,4182,4193,0)
      ...

For our simple needs, massaging the data into proper JSON to use a parser is unnecessary. A regex can cleanly capture the names inside the quotes and their values. We then store the name value pairs in a hash.

1
2
3
if ( $line =~ m/"([^"]+)" = (.*)$/ ) {
    $data{$1} = $2;
}

We create an array of the values we actually care about logging. This is done near the beginning of the script, before running and parsing the output of ioreg. If the amount of data was much larger, our simple parser could be made smarter to only store in the hash the values we care about. With only 39 values though, the slightly increased memory usage in the short lived cron job is preferable to the little bit of extra CPU to check if we want a value before storing it.

1
2
3
4
my @logged = ( qw(
        CurrentCapacity MaxCapacity Pcnt CycleCount LifePcnt
        ExternalConnected IsCharging FullyCharged Temperature CellVoltage
) );

We can then take advantage of hash slices to write out just the values we care about:

1
say $fh join( "\t", time, @data{@logged} );

@data{@logged} becomes a list of the hash values for the keys earlier specified in @logged.

The full script weighs in at only 28 lines of straight forward code. See just it here.

GitHub Repo

In Perl, Debugging With Binary Data Structures

Perl has some really great tools for dumping datastructures when debugging. Data::Printer by GARU is a realitive new comer that’s gained a tremendous following. Of course, everyone also knows Data::Dumper, core since at least perl 5.5 in 2004. What do you do when you need to dump binary data though?

I recently had to do this for the first time so I went looking on the CPAN to see what was available. I found two modules that both made dumping binary data simple. Data:HexDump and a more recently updated Data::HexDumper. Both have similiary simple usage:

1
2
3
4
5
6
7
use Data::Hexdumper;
use Data::HexDump;

my $binary_data = get_some_bin_data();

print hexdumper $data;
print hexdump $data;

I started with the much more configurable and more recent Data::HexDumper. The only draw back was some of my data generated warnings when printing. You could turn this off with either of:

1
2
3
print hexdumper (data => $binary_data, suppress_warnings => 0);
# or
print hexdumper $binary_data, { suppress_warnings => 0 };

but both were two much typing for a lazy Perl developer. I ended up installing and switching over to Data:HexDump. This module has no configurable options but didn’t generate warnings with my sample data.

For simple situations, Data:HexDump seems a suitable choice at 4k. Even you want control over the output, and there is lots of control offered, Data::HexDumper does it in only 13.6K.

Here’s sample output for both, with default options for Data::HexDumper.

Data::Hexdumper

1
2
3
4
5
6
  0x0000 : B4 2D 81 35 D0 16 23 4C F4 ED 23 64 60 AB FC 37 : .-.5..#L..#d`..7
  0x0010 : 0C CA 60 C7 3F A2 58 75 53 CD 78 DF D3 0C 16 18 : ..`.?.XuS.x.....
  0x0020 : B7 CD 92 95 A2 E1 54 3A F3 89 7A 88 89 28 05 4A : ......T:..z..(.J
  0x0030 : 1B 18 C9 2F 61 8D 49 83 E6 2B 18 96 A6 40 8F BA : .../a.I..+...@..
  0x0040 : 44 0D A4 02 1E D2 01 E3 9F 1C 63 47 94 80 9B 74 : D.........cG...t
  0x0050 : 0C D1 63 46 0A 89 B5 1F F3 A7 68 4C 14 1B E6 2E : ..cF......hL....

Data::HexDump

1
2
3
4
5
6
7
8
      00 01 02 03 04 05 06 07 - 08 09 0A 0B 0C 0D 0E 0F  0123456789ABCDEF

00000000  B4 2D 81 35 D0 16 23 4C - F4 ED 23 64 60 AB FC 37  .-.5..#L..#d`..7
00000010  0C CA 60 C7 3F A2 58 75 - 53 CD 78 DF D3 0C 16 18  ..`.?.XuS.x.....
00000020  B7 CD 92 95 A2 E1 54 3A - F3 89 7A 88 89 28 05 4A  ......T:..z..(.J
00000030  1B 18 C9 2F 61 8D 49 83 - E6 2B 18 96 A6 40 8F BA  .../a.I..+...@..
00000040  44 0D A4 02 1E D2 01 E3 - 9F 1C 63 47 94 80 9B 74  D.........cG...t
00000050  0C D1 63 46 0A 89 B5 1F - F3 A7 68 4C 14 1B E6 2E  ..cF......hL....

Alfred 2 Workflow for Audio Device Selection

Alfred V2 has a great new feature called workflows. I’ve been playing with a few others wrote and had ported my old custom commands to workflows but was looking for something to really make use of their power.

Changing OSX Audio device from menubar Changing the selected audio output device was just the thing to implement as a workflow. OS X has a nice shortcut for doing this without heading to system preferences. Option clicking the speaker in the menu bar well let you change the input or output device, but I wanted to do it easily from the keyboard.

The ‘Script Filter’ option under the input menu is the magic for this workflow. It allows a script to output a list of items for display and selection in the Alfred GUI. You get Alfred’s great predictive auto complete which makes selecting a device a breeze.

Selecting output audio device in Alfred

Output via Growl or Notification Center provides feedback of the completed action.

Growl confirmation

The workflow is pretty simple in Alfred’s workflow editor, it ends up looking like this:

Alfred work flow

Alfred makes sharing workflows insanely easy by throwing all the necessary files for each workflow in a dedicated directory. Right clicking a workflow in Alfred gives an export workflow option which creates a zip file of this directory with the ‘.alfredworkflow’ extension.

Grab SwitchAudio.alfredworkflow

The heavy lifting is done by switchaudio-osx by deweller on GitHub with a simple perl glue script to pass data back and forth between Alfred and switchaudio-osx.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/env perl

use strict;
use warnings;

use FindBin;

my $action = shift || 'list';
my $direction = shift || 'output';

if ($action eq 'list') {
    my $devices = get_possibilities($direction);
    print qq{<?xml version="1.0"?>\n<items>\n};
    print output_device($_) for @$devices;
    print "</items>\n";
}

if ( $action eq 'set' ) {
    my $device = shift;
    print set_device($direction, $device) . "\n";
}

sub get_possibilities {
    my $direction = shift;
    my @devices;
    open( my $fh, '-|', $FindBin::Bin . '/SwitchAudioSource',
        '-at', $direction );
    while ( my $line = <$fh> ) {
        chomp $line;
        $line =~ s/ \(\Q$direction\E\)$//;
        push @devices, $line;
    }
    close $fh;
    return \@devices;
}

sub set_device {
    my ( $direction, $device ) = @_;
    open( my $fh, '-|', $FindBin::Bin . '/SwitchAudioSource',
        '-t', $direction, '-s', $device );
    my $output = join "\n", <$fh>;
    close $fh;
    return $output;
}

sub output_device {
    my $device = shift;
    ( my $device_no_space = $device ) =~ tr/ /_/;
    return qq{<item arg="$device" uid="$device_no_space"><title>$device</title><subtitle/><icon>icon.png</icon></item>\n};
}

Fair Trade Coffee Price Premium

Galloway Township considered a resolution last week that would support fair trade practices. The resolution was tabled after some brief discussion. The cost difference between fair trade and non fair trade items was brought up and I was curious how much of a difference there was.

The town currently gets most office supplies from WB Mason. I do not know if this includes coffee but at work we get our coffee from WB Mason so as any Geek would do, I made a spread sheet.

Direct Link to Google Docs Spreadsheet

There are only two fair trade items in this category but they are right in line with prices for non fair trade varieties. If you are already using one of the non fair trade blends from the two companies with a fair trade blend, there is 0 price difference.

This lack of price difference surprised me.

ZSH Completion Waiting Dots

ZSH has some pretty nice tab completion but some of the completion modules can make things slow when you have a high latency conection. This can be extra harsh for me as I have failure to complete beeps turned off so I’m not sure if it’s still trying to complete or if there were no matches. When reading some zshrc snippts on Stack Overflow I came accross my favorite new snippit.

This snippet from a paid nerd adds ‘…’ output during completion that is replaced with the completion or removed once the completion engine is finished.

Here’s the snippet:

1
2
3
4
5
6
7
8
# http://stackoverflow.com/a/844299
expand-or-complete-with-dots() {
  echo -n "\e[31m...\e[0m"
  zle expand-or-complete
  zle redisplay
}
zle -N expand-or-complete-with-dots
bindkey "^I" expand-or-complete-with-dots

Also, get yourself in the habbit of including a comment with a url for stuff like this. I once wanted to write a blog post about something I found somewhere and couldn’t remember where I found it online! I’ll never make that mistake again.

Syncing Zsh Named Directories

One of my most used features of zsh is named directories. I keep my dotfiles synced across multiple machines via Dropbox (referral link) and a Makefile that creates symlinks automagically.

My named directories start with ~ for my home directory so they need to exist for expansion to work properly and not output errors when I log in. When I first implemented syncing I added this check with a very simple test:

DHS NOC MNC Poor Security Examples

The Media Monitoring Capability of the The Department of Homeland Security’s National Operations Center is tasked with keeping existing situation summaries for both domestic and international events up to date with open source media information. Their second mission is “to constantly monitor all available open source information with the goal of expeditiously alerting the NOC Watch Team and other key Department personnel of emergent situations”. This means monitoring both various online news sites as well as social networking.

Through a Freedom of Information Act request their Analyst’s Desktop Binder (4.4 MB PDF) was made publicly available. This is essentially the employee manual for MMC analysts, describing how to preform their job. There are quite a few very interesting tid bits in it such as the list of keywords and search terms used when searching social media sites.

Tweeting Thermostat

I recently replaced the thermostat in our new house with a Filtrete 3M-50. This thermostat has a wifi module and is available at your local Home Depot for $99. I’d been aware of it for a while but had planned on purchasing the $250 nest. The turning point for me came one even as I was going to bed. I was hot, the heat was running and I chose to turn the fan on instead of going downstairs and adjusting the thermostat. In my defense, I knew the thermostat would switch to night mode in another 45 minutes and reduce the set point but I was still wasting energy.

Comparing the Filtrete to the nest the main features you are missing out on are: