Sunday, June 5, 2011

Using google-voice-dialout.agi With Asterisk, Sipgate And Google Voice


Paul Marks has a neat Python AGI script for Asterisk - google-voice-dialout.agi - that will login to your Google Voice account and place a call for you. This script is intended to allow you to place free outgoing calls from your home SIP phone (like a Cisco 7960 which is what I've got set up right now) using Google Voice and Gizmo5. Mario has a bunch of blog posts explaining different ways of doing this including a simpler setup with Google Talk, using the Jabber/Jingle support in Asterisk 1.8. His dial-plan also includes bridging of your outbound call and Google Voice callback so you needn't answer the call back from Google Voice.

Gizmo5 has since been acquired by Google and isn't accepting new sign-ups any more so if you didn't get an account earlier or need a second account to support a roommate or spouse's Google Voice number, you're out of luck there. However, there are other services available and I came across Sipgate in this Lifehacker post.

Sipgate has a help article that explains how to set up Asterisk to work with their service. Now, to make outgoing calls, I copied the basic dial plan for Asterisk from Mario's post with one little change to the Google Voice dialout script - change the value of phoneType to 2 instead of 7. From what I can tell 2 is for regular numbers, 7 is for Gizmo5 numbers and 9 is for Google Talk.

Credit: Recycle icon from Obsidian Dawn

Sunday, February 27, 2011

Color Clock - Representing Time As A Hexadecimal Color Value

I came across a post in my Facebook feed today that linked to The Colour Clock by Jack Hughes. It's a pretty neat idea - the current time is translated into a hexadecimal color value and applied to the background of the page. So as the time changes, the background color of the page changes as well.

The only thing is, it's in Flash so if you're on an iOS device, you won't be able to see it. Or if you'd like to pull it up on your web-enabled TV or other device that doesn't have Flash. So I spent my Sunday afternoon porting it over to JavaScript and this is what I have: http://colorclock.nogoodatcoding.com. Can you spot the original?



Will the real Color Clock please stand up?
It's the one on the left.
  

I've tried to stay true to the original but among other things, my colors are just a little off, most likely because I'm calculating them differently. You can find project details on my site.

 Cross-posted from The No Good Blog
 

Saturday, February 19, 2011

JDOM - getChild() Or getChildText() Returns null

If you're using JDOM for parsing XML in Java and you run into the problem that Element#getChild(String) and Element#getChildText(String) just keep returning null, here's a list of reasons why that might be happening:
  1. The node really doesn't exist!
  2. The node is in a different namespace and you need to use the version of the method that also accepts the namespace: Element#getChild(String, Namespace) or Element#getChildText(String, Namespace).
  3. Most importantly, remember that these methods return only immediate descendents of a node! So if you're looking to get a node nested at the nth level, you will need to walk the tree to its parent and only then can you call #getChild() and actually get the child!

Saturday, February 12, 2011

Facebook created_time format in JSON response

I was trying to get relative times for Facebook posts for fbbash, using the time returned in JSON objects using the Facebook JavaScript SDK. The created_time looks something like 2011-02-12T11:58:46+0000

The part before the 'T' is the date in a 'YYYY-MM-DD' format. And after is the time in 'HH:MM:SS'. As far as I can tell, the trailing '+0000' is the timezone offset but I've only ever seen that value so I've made the assumption that you're getting times that are GMT more or less (or UTC if you want to get technical).

I found this script on Stack Overflow by no, that converts this timestamp into a relative time string such as '5 min ago'. Unfortunately, despite what the comments on the script say, simply calling
fuzzyFacebookTime('2011-02-12T11:58:46+0000'); //doesn't work!
doesn't return the right value - instead, it gives back 'NaN years ago'.

The easy fix to this problem is to change the timestamp you're passing to the function to the form YYYY/MM/DDTHH:MM:SS+ZZZZ i.e. change the hyphens (-) to slashes (/). That seems to work and you should get the correct string. So you can make the call
fuzzyFacebookTime('2011-02-12T11:58:46+0000'.replace(/-/g,'/'));

Here's the script:
var fuzzyFacebookTime = (function(){

  fuzzyTime.defaultOptions={
    // time display options
    relativeTime : 48,
    // language options
    monthNames : ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    amPm : ['AM', 'PM'],
    ordinalSuffix : function(n) {return ['th','st','nd','rd'][n<4 || (n>20 && n % 10<4) ? n % 10 : 0]}
  }

  function fuzzyTime (timeValue, options) {

    var options=options||fuzzyTime.defaultOptions, 
        date=parseDate(timeValue),
        delta=parseInt(((new Date()).getTime()-date.getTime())/1000),
        relative=options.relativeTime,
        cutoff=+relative===relative ? relative*60*60 : Infinity;

    if (relative===false || delta>cutoff)
      return formatTime(date, options)+' '+formatDate(date, options);

    if (delta<60) return 'less than a minute ago';
    var minutes=parseInt(delta/60 +0.5);
    if (minutes <= 1) return 'about a minute ago';
    var hours=parseInt(minutes/60 +0.5);
    if (hours<1) return minutes+' minutes ago';
    if (hours==1) return 'about an hour ago';
    var days=parseInt(hours/24 +0.5);
    if (days<1) return hours+' hours ago';
    if (days==1) return formatTime(date, options)+' yesterday';
    var weeks=parseInt(days/7 +0.5);
    if (weeks<2) return formatTime(date, options)+' '+days+' days ago';
    var months=parseInt(weeks/4.34812141 +0.5);
    if (months<2) return weeks+' weeks ago';
    var years=parseInt(months/12 +0.5);
    if (years<2) return months+' months ago';
    return years+' years ago';
  }

  function parseDate (str) {
    var v=str.replace(/[T\+]/g,' ').split(' ');
    return new Date(Date.parse(v[0] + " " + v[1] + " UTC"));
  }

  function formatTime (date, options) {
    var h=date.getHours(), m=''+date.getMinutes(), am=options.amPm;
    return (h>12 ? h-12 : h)+':'+(m.length==1 ? '0' : '' )+m+' '+(h<12 ? am[0] : am[1]);
  }

  function formatDate (date, options) {
    var mon=options.monthNames[date.getMonth()],
        day=date.getDate(),
        year=date.getFullYear(),
        thisyear=(new Date()).getFullYear(),
        suf=options.ordinalSuffix(day);

    return mon+' '+day+suf+(thisyear!=year ? ', '+year : '');
  }

  return fuzzyTime;

}());
Image Credit: ThinkDiff.net

 UPDATE [1235 20 Feb 2011]: Added an image and fixed some formatting

Sunday, August 1, 2010

Garmin nüvi 255W Crashes On Choosing A Favorite POI

Garmin nüvi 255W GPS
I recently bought a recertified Garmin nüvi 255W GPS from NewEgg.com - I've only had it a week and since I don't have a car yet, I've only tested it by using it on the bus and while walking; seems to be working fine so far.

Except for one thing – sometimes, when I selected a destination, the unit would inexplicably crash – it would just turn off. The first couple of times, I wrote it off as a random glitch and got the software update that was available at myGarmin. But that didn’t solve the problem.

I finally noticed that this only happened when I selected the entry for my home (saved in my favorites list). And it would only happen when I went through the steps really quickly. And when it did happen, the thumbnail for the entry hadn’t loaded completely on screen. That’s right, I had a photo of the apartment complex entrance set for this favorite POI.

So as it turns out, it seems that if you have a big image – mine is about 1.5 MB – you’ll likely have a problem. Reducing the size of the image or not associating a photo with the POI seems to fix the problem.

Monday, May 24, 2010

Metapost: Style Updates

Not much to report, just spent a while making minor changes to the look of blog posts -
  • Code snippets now use the excellent SyntaxHighlighter by Alex Gorbatchev (chances are you've seen this already, it's pretty popular, and with good reason!).
  • I've updated the CSS so error, warning, tip and note boxes are all styled. I also went back and updated the posts that were put up before I thought of these. If you want to see what these look like, take a look at the TortoiseSVN with SVN+SSH post or the Hacking the Cisco 7940 IP Phone post.
  • Some minor updates to content and to styles so that everything is more consistent

Saturday, May 1, 2010

Fix for Sony DSC-S40 Blank White LCD Screen


A little while ago, I turned on my Sony DSC-S40 camera and it gave me quite a fright – the LCD viewfinder was completely white! Turning the camera off and back on and changing batteries didn’t help.

So I decided to Google to see if there was something that could be done about it. As it turns out, there’s a simple solution (posted by a Bob Allen) which has helped a lot of owners and when I first read it, I thought it was a joke. The instructions read:

1. Hold camera firmly in left hand
2. Smartly rap front of camera with knuckles of right hand on the "Cyber-shot" logo.



That’s it. Really. And it does work.

According to this discussion on Camera Hacker, the underlying problem is that the LCD ribbon becomes loose and either pressing or tapping the panel at the right spot (the Cyber-shot logo) fixes the issue by pushing the connector back in place.