Wednesday, June 29, 2011

strange programmer habits : literal comes first in a comparison

Consider this JavaScript code:
function foo( aString ) { if( ‘:error’ == aString ) { handleError(); } }
Why put the variable reference after the string literal? So you don't accidentally turn the comparison into an assignment. Look at this code:
function foo( aString ) { if( aString = ‘:error’ ) { handleError(); } }
Do you see the error? The programmer has accidentally dropped one of the equal signs in the comparison operator. If this code was being edited at 4AM the day before a big demo, believe me, it would be hard to spot.
But if put the literal was first and then forgot the extra equals sign, we would get an error. Go ahead and try it. Open up the javascript debugger in your browser and copy this code fragment into it:
( function ( aString ) { if( ‘:error’ = aString ) { console.log( ‘looks like we were passed an error token.’ ); } } ) ( ‘blarg’ );
You should get a syntax error, which should clue you off that you forgot an equals sign. This is a programmer habit seen in most "curley brace" languages (C, C++, Java, Python, etc.) JavaScript programmers may also want to consider using the "strict equal" comparison operator (i.e. the triple equals.) Refer to Mozilla's excellent Javascript Docs for more info.

Tuesday, June 21, 2011

chromium os on a dell mini 9? i like it

so for the last week i've been playing with chromium os. it's the linux-based web-focused operating system from google everyone's been yammering about for the past week. samsung and acer just released a couple "chromebooks," and it seems like the tech press is falling over itself to pan the devices. but i recently took the plunge and installed chromium on my dell vostro a90 (aka mini 9) and here are my impressions.

i like it. (with some caveats)

let me start by saying i'm a bit of a google fangrrl; not a complete fangrrl, but a fangrrl nonetheless. i started taking google services seriously several years ago when i subscribed to gmail. i love it: all my mail is available from any PC i happen to be sitting in front of. i was also an early adopter of writely (later google docs.) i love it for exactly the same reason: my documents automatically follow me around from machine to machine.

so i'm not a google fangrrl in the same way that people can be apple fans. design is important to me, but i'm more interested in the program's interface and capabilities. sure, cool looking hardware is nice, but it's the UX that counts. google's UI for gmail, gdocs, &c aren't "beautiful" in the way that apple interfaces are beautiful; but they're more than good enough. i am also not so much of a google fan that i use google buzz or wave or orkut.

i've been burned by syncing too many times in the past to trust anyone to get it right. i like the google services because they give me document and service mobility without having to think about it. that is my primary consideration.

yes, i occasionally happen to have my netbook powered on when there's no network coverage. and that sucks. for me, the benefits of service mobility outweigh the drawbacks of not being able to get to my docs when the network evaporates.

so i'm sure you've heard of gmail and google docs and picasa. i use them. they're great. however, there are a couple other services you might not have heard about. (and it's okay, these are all pretty much services for software developers.)

one service i kind of had to start using is Cloud9. it's a javascript editor and development environment right in your web browser. it's not perfect, but with the recent git and mercurial integration, Cloud9 is the node.js developer's equivalent of an unstoppable force whose kung fu will defeat the forces of evil. okay. maybe it only seems that way 'cause i'm a fan of storing your stuff in the cloud. but check it out. when my free trial expires, i'm totally giving them the small amount of money they're asking for. your mileage may vary.

in the future, i hope the Cloud9 team convert my money into a group editing / etherpad-esque feature.

so that's basically been my week. i installed chromium on my dell (thanks to the work by Doug Anson of Dell's CTO's Office.) i continued using google services i have been using, and started using (and was impressed by) Cloud9.

and i think the future is going to be even brighter. google docs currently have the problem that they don't make use of HTML5's local storage and web application APIs to provide a compelling "offline experience." (gmail currently has an "offline mode.") but CNET (and others) are reporting that we'll start seeing offline editing features this summer. if/when this happens, one of the largest complaints people have about chromebooks will disappear.

so... chromium on the dell mini-9 is a great alternative to paying $500 for a new laptop; especially if, like me, you happen to have a mini-9 hanging around the house. installing the OS was pretty straight-forward; use the link to Doug Anson's build above; hexxeh flow had some problems loading on my mini-9. but even Doug's work has a few warts:
  1. there's no audio - this is a known problem. Doug says it'll likely get fixed in a future release.
  2. there's no (easy) java - the most recent dell build of chromium doesn't ship with java, and the stock java installer for linux barfs (i'm guessing because of unfulfilled dynamic libraries.) i didn't spend a lot of time on getting it to work, and have seen java work on other chromium builds, so i know it can be done. it's just not easy.
  3. wifi's turned off out of the box - like many linux devices that use broadcom wifi chipsets, you have to download the proprietary drivers using a wired ethernet connection before you can experience wireless bliss. but it's pretty straight-forward to add the drivers. the release notes intimate the dell guys are working with the broadcom lawyers to figure out a way to include the drivers in the stock build, so maybe this problem will go away.
  4. WebGL? if it's enabled in the may 13th build, i've yet to see it work.
so, chromium os on a dell mini 9: i like it. it's not without it's warts, but it's a better alternative than plunking down $500 on a new laptop.

Monday, June 6, 2011

a few new node modules

people who know me know that i love node.js, the javascript network application framework. most of the projects i've prototyped in the last couple of years have been done with javascript in a browser and node.js on the server. i don't know why it took me so long to think about this, but i'm finally releasing some of the tools i developed. (okay, technically, i re-implemented them to avoid some project specific kruft.)

but anyway, in the last couple of weeks i released two node packages: node-props and node-mug.

node-props.js

node-props is a package that lets developers read properties from one or more URIs specified on the command line. so, basically, you can do this:
node application.js --config file:///etc/host_props.json --config https://example.org/app_props.js
i found the ability to grab properties from multiple locations is good for "cloud-like" applications. i use it to separate "host config" parameters (e.g. - addresses & ports to listen on) from "application config" parameters (like db addresses, etc.)

separating the two classes of config info provides a bit of flexibility if you're deploying an array of servers. by placing application config information on a central server, you only need to change a single file to change your app's behavior.

the package has been published to the npm registry and the source is available at https://github.com/OhMeadhbh/node-props

node-mug.js

the node-mug package exports an interface developers can use to generate RFC 4122 compliant Version 4 (random) UUIDs. unlike some other UUID generators for node, node-mug collects entropy from the /dev/urandom file present on most modern *nix systems. paranoid app developers can configure the system to read entropy from /dev/random.

interested users can install node-mug via npm or retrieving the source from the git repository at https://github.com/OhMeadhbh/node-mug

happy coding!

Tuesday, May 31, 2011

fun with node.js - building a node development appliance for virtual box

so... people who know me know i've been raving about this thing called node.js for the last several years. if you haven't heard about it, click over to the wikipedia's entry on node and take a minute to read it, i'll wait.

the simplest description of node would be to call it a "javascript web server." this is a decent description when talking to non-tech folks, though us technorati know it's really an "ecmascript application server framework."

turns out node can do some amazingly cool stuff. what most people have heard about is it's pretty good at handling high load situations. slightly less well known are the benefits of using the same code to render HTML in the server as is used to render HTML in AJAXy client apps running in a browser.

ultimately though, it's just a lot of fun to program apps with node.

so... to help spread the node.js gospel, i put together a virtual box appliance you can use to try it out without the fuss of having to download and compile the core packages yourself. i also added mongodb (and the node driver) to the image so you can play with persistence.

anyway... you can find more detailed info over at the node appliance page on my site. it's not a small download, but the time you lose in the download is more than made up for by the time you save by not having to configure it yourself.

you can find more information about node at the official node website (complete with docs!) and tim caswell's "how to node" site. you can keep up with the node community by following the #nodejs hashtag on twitter, visiting nodejs.se or dropping in on the #nodejs IRC channel.

happy coding!

Sunday, May 29, 2011

on accessing services from within second life

so a few moments ago, @ZauberExonar asked on twitter if anyone was aware of a JSON parser in the Linden Scripting Language (LSL). people unfamiliar with LSL or Second Life(tm) may want to skip this blog posting. in typical "software architect" fashion, i'm answering his question with several paragraphs of "why JSON and LSL don't mix" (and what you can do about it.)

a very brief intro to JSON

JSON, as we all know, is a transfer syntax that encodes messages in a way that looks remarkably like a JavaScript / ECMAScript object declaration. So... if you execute this JavaScript:

var foo = {   success: false,   error: "insufficient cheese error: recommend rebooting universe" };
console.log( JSON.stringify( foo ) );

you would get a JSON blob that looks something like this:

{"success":false,"error":"insufficient cheese error: recommend rebooting universe"}
so far, so good, right? you start with a JavaScript object and you convert it into a string that represents the object using a familiar syntax. it's now ready to send over the network. the receiver can execute this code to deserialize the string version of the message into a real live object:

var bar = JSON.parse( "{\"success\":false,\"error\":\"insufficient cheese error: recommend rebooting universe\"}" );

and now the receiver has an object it can manipulate.

the cool thing about JSON as a transfer syntax is messages are serialized using encoding rules that are way easy to process in JavaScript (the programming language of the web.) so it's easy to understand why web-devs love the heck out of JSON.

XML, in comparison, is seemingly bloated. XML allows you to define your own tags, each with semantics specific to the message. this can be a good thing in some situations, but you have to add the smarts to your JavaScript application to grab specific bits of data out of the XML and construct objects to contain the data.

enter the virtual world

but if we want to consume a JSON service in the virtual world, things get a little complicated. in Second Life, the programming language of choice is LSL (Linden Scripting Language.) a lot of people love to hate on LSL. i'm not going to do that here. but i will say this: parsing JSON or XML in LSL is a pain in the ass.

perhaps the most irritating aspect of LSL in this regard is it's lack of associative arrays. whether you call them maps, dictionaries, objects or associative arrays, they all let you use a string as a key into a collection of items.

because there's no associative array in LSL, you can't pull off the JavaScript trick of creating a new object that's essentially identical to the JSON. no, you have to map the contents of the JSON string into a list (which is like an array) or global variables.

JSON lovers aren't alone... XML partisans have discovered they're in the same boat: you have to parse the message and reason about the semantics of each field while constructing a list or setting global variables.

easy parsing?

and another aspect of JSON and XML parsing in LSL that's sub-optimal: you have to write LSL to look at each character in the message string.

okay, this is not precisely true. if your message does not include escaped quotes or curly braces, you can use llParseString2List() to build a list that's MUCH easier to parse. the down side of this approach is it's not entirely easy to handle curly braces inside strings and honestly, the code to implement it frequently looks bizarre.

so what i've started to do is to use a LSL-friendly format i'm calling the "DSD Text Transfer Syntax." experienced readers will recognize DSD as the abstract type system i routinely threatened the VWRAP group with. DSD text looks like this:

:v:1
appkey:u:77c3dd7c-4639-4681-aa52-a7dd35e96fd8
:{:
success:0:
error:s:insufficient%20cheese%20error%3A%20reboot%20universe
errno:i:23
desc:l:http%3A//example.com/error_descriptions/cheese.html
:}:

messages are a collection of individual lines (separated by either a CR or a CRLF.) each line contains three fields separated by colon characters. the first field is a "name" field; the second is a "type tag" while the third is the data in question. note that not all lines have a name, and not all lines have a data field. also note that colon characters are verboten in the data field, so we encode strings and URIs that may contain them.

people familiar with the LLSD binary encoding will likely recognize the tag characters, they're directly ripped off from that spec. (i also added a version tag so parsers will be able to know when they receive a message they may have problems interpreting.)

so the way you parse this in LSL is to split a message into lines like so:

// assume the string 'message' contains the complete message text
list lines = llParseString2List( message, ["\n", "\r", "\n\r"], [] );
integer lineCount = llGetListLength( lines );
integer i;
for( i = 0; i < lineCount; i++ ) {
string currentLine = llList2String( lines, i );
list fields = llParseString2List( currentLine, [":"], [] );
string name = llList2String( fields, 0 );
string key = llList2String( fields, 1 );
string data = llList2String( fields, 2 );

// now process the name-key-data triple
}

what you do when you process the name, key and data values depends on your app. i find i'm frequently either stuffing them into global variables or constructing new lists with the values. to parse the message above, we do something like this:

// parse location info message. generates a list with the following members:
// 0 - integer - success (1 for success, 0 for failure)
// 1 - integer - errno (0 for success)
// 2 - string - error description ("" if call was successful )
// 3 - string - URL for more information ("" if call was successful)
// 4 - string - region name
// 5 - float - x location in region
// 6 - float - y location in region
// 7 - string - comment text

list parseLocationInfoMessage( message ) {
integer success = TRUE;
integer errno = 0;
string error = "";
string desc = "";

integer in_map = FALSE;
integer version;

string region = "";
float x = 0.0;
float y = 0.0;
string comment = "";

list lines = llParseString2List( message, ["\n", "\r", "\n\r"], [] );
integer lineCount = llGetListLength( lines );
integer i;

for( i = 0; i < lineCount; i++ ) {
string currentLine = llList2String( lines, i );
list fields = llParseString2List( currentLine, [":"], [] );
string name = llList2String( fields, 0 );
string key = llList2String( fields, 1 );
string data = llList2String( fields, 2 );

// now process the name-key-data triple

if( 'v' == key ) {
version = (integer) data;
if( 1 != version ) {
success = FALSE;
errno = -1;
error = "invalid message version";
break;
}
} else if( '{' == key ) {
in_map = TRUE;
} else if( '}' == key ) {
in_map = FALSE;
} else {
if( FALSE == in_map ) {
success = FALSE;
errno = -2;
error = "parsing error";
break;
}

if( 'success' == name ) {
if( '1' == key ) {
success = TRUE;
} else {
success = FALSE;
}
} else if( 'errno' == name ) {
errno = (integer) data;
} else if( 'error' == name ) {
error = llUnescapeURL( data );
} else if( 'desc' == name ) {
desc = llUnescapeURL( data );
} else if( 'region' == name ) {
region = llUnescapeURL( data );
} else if( 'x' == name ) {
x = (integer) data;
} else if( 'y' == name ) {
y = (integer) data;
} else if( 'comment' == name ) {
comment = llUnescapeURL( data );
}
}
}

return( [ success, errno, error, desc, region, x, y, comment ] );
}

some might argue this is no less complex than XML or JSON parsing in LSL, but for my money, it seems a little more straight-forward.

making services give you DSD Text

ideally you're in a position to control both the server and the client. if you are, then your server code gets to decide what type of encoding you send back to the client. slatebureau.com uses the same API endpoints for requests, irrespective of where they come from. to determine what encoding to use, it looks for the Accept:, Content-Type: and S-SecondLife-Shard: headers in the request and uses this algorithm.

  1. if an Accept: header is present, and you can generate the mime type the client is requesting, use it. if you can't generate the encoding requested, send a 406 status code.

    in other words, if you ask for a 'application/json' or 'application/dsd+json', i'm going to give you JSON. if you ask for 'text/plain' or 'application/dsd+text', i'm going to give you the text format described here.

  2. if there's no Accept: header but there is a Content-Type: header present in the request, send the response in the format of the content type. if you can't generate that encoding, don't freak out, continue to step 3.

    so if there was a Content-Type: header in the request and there wasn't an Accept: header, i'm going to try to encode the response using the same type. if your request included a json blob with an 'application/json' Content-Type, i'll try to generate that as a response.

  3. send a DSD-Text formatted response.

so... anyway... i wrote a few DSD parsers in PHP and JavaScript. i'll try to dig them out and post them to github. -cheers!

Sunday, March 20, 2011

the return of hbmobile.org

so i'm in the process of turning the hbmobile.org web site back on, and i'm going back to spending my spare time making gadgets. there's a big long story behind this, so let's take it piece by piece.

i work for klout.com right now, but for a big chunk of my career, i worked for companies in the mobile value chain. most of the time i worked there, i wondered "why do mobile phones suck so hard?"

we all have some pretty great phones available to us at the moment, so it's easy to forget: before the iPhone and Android OS, being a developer on a mobile device was expensive, difficult and frustrating. expensive 'cause you frequently had to pay tens of thousands of dollars for development systems before you could even begin to start developing a mobile app. difficult 'cause you had to learn an entirely new operating system and dev platform and frustrating 'cause the mobile OS vendor, handset manufacturer or carrier would frequently hobble your app beyond recognition.

back before Android and iPhone, a bunch of us hobbled together our own DIY phones without these problems. Surj Patel and Deva Seetharam put together a "TuxPhone" back in 2005-2006. I spent some time putting bits of hardware and software together in 2006, while Craig Hughes and Gordon Kruberg of gumstix.com did some heavy lifting, building a GumStix daughterboard populated with a mobile phone chipset.

we also had this group called "the homebrew mobile phone club." modeled on the earlier "homebrew computer club," the idea was to provide support and encouragement for people building their own devices.

in 2008, the group fell apart. partially 'cause i had to concentrate on getting divorced. but also 'cause we were getting more or less what we wanted from the mobile industry. the iPhone and Android used familiar operating systems and well known development tools; you didn't have to pay google or apple insane amounts of cash for dev systems and you more or less had access to all of the phone's hardware.

for the most part we declared victory and moved on with our lives.

we did do a lot of very cool stuff. Adrian Cockroft used the "myPhone" project as an excuse to learn how to develop enclosures for mobile devices. i wrote a hack of a lot of control software for GSM modems. and Craig & Gordon did an insanely good job of developing open hardware that could send and receive phone calls and text messages. James Young saved our old wiki at the hbmobile.org backup; go check it out, there's a lot of cool stuff there.

sure... it's not that big of a deal when you compare it to what HTC and LG do, but remember, we were a bunch of individuals with soldering irons, extra cash and a few extra hours per week. we proved you didn't HAVE to be a multi-billion dollar company to build a mobile phone.

that the myPhone was more expensive than a subsidized iPhone, and had fewer apps than Symbian was not the point. the point was, we were able to build it on our own. we also shared as much as we could, using open source and creative common licenses for most system components. (read my blurb for O'Reilly called "the complete open phone" for the rationale behind this decision.)

so... we did a lot of cool stuff and moved on with our lives.

but now i'm reactivating the hbmobile.org domain to work on a new project.

AT&T has announced they're going to buy T-Mobile. This is a bad deal for everyone (except AT&T share-holders.) Om Malik has a great blog post on why it's a bad deal here: "In AT&T and T-Mobile Merger, Everybody Loses."

for the last year i've been worried by moves from the carriers: price increases, charging for tethering, wireless bandwidth caps, etc. and now we're falling towards monopoly in the GSM world.

i'm going to spend my spare time for the next couple months trying to solve the "quality communications services over unlicensed spectrum" problem. i'm not trying to dislodge AT&T or Apple or Microsoft. i'm not trying to build mobile phones that will be the next big thing at SxSW. i want to build some prototypes of systems that sidestep licensed spectrum and the problems of carving it up and giving it to monopolies.

if you're interested, take a look at the new hbmobile.org site. subscribe to my blog feed and consider listening to my rants on twitter.

if it makes sense, i'll also be hosting meetings in san francisco (and in second life.) stay tuned!

Saturday, March 12, 2011

radiation monitoring station

so sparkfun.com has this geiger counter device i've been eyeing for a year or two. (actually, i think this is an updated version of the one i was lusting over.) and now that we've apparently had an explosion at Fukushima 1, i believe we'll see an increase in environmental radiation. fwiw, someone posted a video of the explosion, if you haven't seen it already.

my college friend wilbur related to me that during the chernobyl meltdown in the 80's, his high school science teacher tracked the rise and decay of environmental radiation. that always seemed like a fun project to me. sort of like a weather station, but in touch with current events.

anyway, so i'm going to order one of these things tomorrow night. if we can get 10 people in the bay area, we could even do a group buy (ping me on twitter at @OhMeadhbh.) but i think tomorrow i'll be setting up a website to track decay events and map them on a google map.

cheers!