this is aaronland

Little Partial(ly Cloudy) Castles

Release notes are the new novel

It goes without saying that (nearly) everyone brought their laptops to the News Years weekend in Sonoma.

I played a game of semantic bullshit and brought only a fancy-pants Nokia tablet. One of the things I like the most about the new OS2008 models is the polite throbber that gently blinks when you receive email, or an instant message or some other event that an application thinks it should tell you about.

You can see where this is going.

There are even Python bindings for sending various types of notifications but since I still haven't figured out the magic to talk to the throbber I spent the weekend periodically poking at the plain old web to see what was going on.

Of course, when I got home all the little Growl-based notification agents I've been writing woke up and spewed four days worth of hot friend action all over my screen. Computers. They're dumb like that.

So, now you can specify a skip_items_older_than preference in the config file and ignore anything older than an hour or a day or whatever. I suppose it might be neat to write some magic to set that option dynamically based on the last time an application was able to register the presence of your pho^H^H^Hdevice, but not today.

Instead, there is only the quick and dirty :

Meanwhile, here's a long photo of us eating dinner.

old(1.0) != new(1.0)

The code discussed in this post has been pulled apart and packaged in handy little feature-specific bundles complete with proper Python installation scripts. They are :

The only caveat is a known bug where searching for nearby Bluetooth devices will get stuck in some sort of infinite loop. I don't know why or, even, how to reproduce the problem. From a distance it appears to be something happening at the (OS X) operating system layer but more investigating is necessary.

As mentioned, there is nothing especially OS X specific about any of this beyond the Growl bindings and every operating system has at least one functional equivalent. At some point, I may also port it to use any number of notification agents.

But not today.

My Inbox is full of rocks

This morning, I was reminded of the quick-and-dirty-and-ugly Perl module for graphing the relationships between email messages that I wrote a few years ago. As usual there is no magic since it simply hands all the hard work to GraphViz and treats everything as sticks and rocks.

I know that some people like to imagine that there is actual knowledge (or if you are a timesome doorknob, agency) to be teased out these things but I prefer to think of them more as Auggie Wren devices. The value for me is to collect a lot of them and then try to feel the elephant over time; to imagine the patterns as a halftone screen with which to rasterbate everything else.

With that in mind I dug out the code just to see if it still worked and, in the process of all the usual bugfixes, decided to teach it a few new tricks.

Here's my Inbox, with just basic To:, From: and Cc: relationships plotted :

Here's the same thing with three sets of email addresses treated as equivalent and aliased to each other when the whole thing is rendered :

Here's the same thing with both equivalencies and a cluster of email addresses — for example, all the addresses for a group of people who work together — represented by ... a box. Oh well :

Finally, the code to do all of this is :

      my $graph = ASCOPE::Email::Graph->new({'obscure' => 1});
      $graph->add_mbox("/path/to/mbox");

      $graph->add_equivalencies(["me\@work.net", "me\@home.net",
                                 "me\@gmail.com"]);

      $graph->add_equivalencies(["buddy\@cheezburger.com",
                                 "bud.dy\@ohhai.com"]);

      $graph->add_equivalencies(["girly\@cheezburger.com",
                                 "grrrr.ly\@ohrly.com"]);

      $graph->add_cluster(["buddy\@cheezburger.com", "bud.dy\@ohhai.com",
                           "girly\@cheezburger.com", "grrrr.ly\@ohrly.com"],
                           "cheezburger");

      $graph->as_png("/path/to/graph.png");
                    

Clearly the next thing to do is to teach the code to read in an address book and generate those equivalencies and clusters on the fly. Maybe I will do that before another three and half years have passed. Colour-coded arrows too but that looks like it might require actual work...

Related, there are some interesting threads to pull by FOAF-ifying all those addresses and feeding them back in to the cloud. (The code already supports the hashing of addresses; I just obscured everything in the examples above because I ph33r you.) I doubt this will ever happen because one side-effect of the current social share-my-graph fetish is that it will be even easier to dereference and harvest mbox_sha1sum addresses — and the Creepy People surely will — but there are certainly some possibilities to explore.

Meantime : ASCOPE::Email::Graph.pm 0.2

Your door is an Interjar

With the enormous amount of money and effort it takes to get together with people you barely see, all of the tensions will be exaggerated. I can see people saying, I spent all this money, I came all this way and for what? It’s supposed to be a certain way. It puts an enormous amount of pressure on those kinds of contacts and connections that wouldn’t be there normally.

Vered Amit

ZOMG!! ADDRESSBUCKET RUN OUT OF INODEZ!!!!

There's a pretty great video, making the rounds, of Dan Hill's presentation at Interesting South titled : The Well-Tempered Personal Environment.

It's basically the idea of displaying real-time consumption stats on or nearby your fantastic Earth-destroying lifestyle-enhancers (read: the faucet) to help you better appreciate the old saw about thinking globally and acting locally. Fantastic! Everyone loves data pr0n and to the extent that it reminds people that we still live in a community of individuals I am all for it.

As an (increasingly tangential) aside, the only part that irks me is where the whole idea is wrapped up the games and play. spandex. This is standard design-for-shame, as well it should be, and pushes all the same buttons that make you invite people over for dinner in order to force yourself to mop the floors. I like playing games too (actually, that's a lie) but this is a perfectly acceptable crutch while we work on the larger issue of human sloth and greed so let's at least be honest about our motivations.

But that's not what I wanted to talk about.

At one point he says Well, these are just mock-ups. We probably don't want to walk around with big numbers floating over everything. We'll want something more in the design of everyday things vein.

Which I thought was curious because it seems so very wrong. Or rather, no one really wants to interact with any of this data. They just want it to be continuously partially present.

Consider Twitter : The part where your phone is either pestering you its horrible YOU HAVE A NEW TEXT MESSAGE sound every two or three minutes, just so someone can tell you they're making hummus — or the part where Continuous Partial Attention is greedspeak for Death By Micropayments if you don't have a phone with unlimited text messages — generally means that people turn off the notify-by-SMS feature.

I would have never bothered with Twitter if I hadn't able to have incoming notifications sent to my IM client where I can continously partially ignore them.

ZOMG!!! WE IS TEH ROBOT SOCIALLORDZ IN UR SAVIN!!!!

But when I woke up with a hangover, last week, I couldn't even be bothered to reach out and switch windows, and then fiddle with tabs, just to know that Dunstan was doing push-ups in bed. I did not want to move but I was awake and staring vaguely at my screen hoping that the power of my social network would simply give me Digital Brain Rub.

Having nothing at all to do with hangovers, you can trace this long line of desire from the movies, to television, to IRC backchannels and hecklebots at conferences, to Twitter itself and then the public Twitter display at SXSW in 2007 (hardly novel, O'Reilly also did something similar with its attention stream at ETech in 2005), to screensavers, to digital frames ranging from consumer level devices tied to partner providers to spaceship-aware Linux distributions wrapped up in shiny paper all the way to full-on Ray Bradbury installations.

I know some people who say things like : I want to be permanently jacked-in to the Internet! I want to have a direct IRC-link to my brain!! I WANT TO SEE LOGFILEZ ON UR FACE!!!! Okay, no one's actually said that last part but it's what they're thinking. And while I think it's mostly crazy talk — try to imagine the world around you pulling a cover flow everytime you turned your head — I also think it ultimately comes from a good place.

One really fantastic by-product of the Network is that it has afforded people, still separated by the cold hard heart of flesh and blood and time and space, the ability to maintain enough shared experience to keep relationships in bloom. Make no mistake : We all die some day and no one wants to be lonely in the tiny bookends we manage to tease out of time's ... continuous partial attention.

The argument that Internet is, as the drunken 23-year old PolySci student I lishly tried to have a rationale argument with described, a great isolator has some merit. Watching people pass hours in front of their computers playing games, writing code or ranting (is there a difference?) otherwise indifferent to any warm-blooded creature nearby is enough to give anyone pause.

I've watched the cycle enough, though, to be pretty certain that's not the case. Sooner or later all communities that comes together online meet offline whether it's gamers who fly to distant towns to, yes, play games together in the same room, or Flickr users who meet to take pictures together, to the 2 to 70 people who have met regularly every month for six years running and share nothing more in common than a city and an appreciation of weblogs, the Internet and beer.

I think everybody instinctively knows that a life online is not enough by itself but that understanding is also not always enough to push us beyond the predjudices and insecurities we bring to a room full of strangers. When it works, the Internet and an individual's ability to project something about themselves out there provides just enough of a bridge between people who've never met to want to entertain the idea of a friendship.

Accelerated serendipity.

Societies have always had norms and conventions for doing the same thing and they've always kept pace or adapted themselves to the available technologies. That the Internet allows people to More Better dance the tune on their own terms I think is an improvement.

But I was talking about Twitter, wasn't I?

ZOMG!! I WAS YAWNING AND THEN I BURPED!!!!

If the Internet is a single bridge connecting two people at the start of a relationship I like to imagine it becoming a series of bridges over a canal that keep the land on either side of the water from straying too far.

Again, you could replace Internet with available media and follow the same thread back through history as far as you wanted.

What's changed obviously is the collapsing of the space between the sending out and receiving of our bird calls. A permanent arrivals and departures lounge of human relationship, where everyone you know is paging you on the white courtesy phone (in your pocket).

This too has long been talked about but since it's only now becoming a practical day-to-day reality so we're finally struggling to figure out whether or not it was a good idea.

Chris summed it up nicely earlier this year : Of course, it doesn’t mean anything will necessarily happen, but you’ve created a possibility space for things to happen in.

I sometimes complain about especially enthusiastic Twitter contacts but, really, I am delighted by the whole thing. I love being a able to share a frame of reference — a pithy text messages or photos or music; anything important (important) enough that you might share it over a meal, — with people who can't be near, either because of geography or mundane daily circumstances. It's a kind of jerky stop-motion animation frame of reference, for sure, but without it you are deaf to the tiny anecdotes in a person's life; the daily rituals and gradual changes in tone and focus that help to nuture the understanding and appreciation of a friendship.

A possibility space.

ZOMG! IM IN UR MEMREEZ PRETENDIN I WUZ THERE!!!!!

Of course, it doesn't take long before it becomes a lot of, and usually too much, work to sift through all that chatter. Especially when you're hungover. Which is why I sitting there, drinking coffee, thinking : Wouldn't it be really nice if new messages could Just Appear in tasteful, discrete windows. Something like Growl notifications. Then the nice people at Google reminded me that I had already written the thing that I was looking for.

At the time, I still wanted to get notitications on my phone but found everything about the experience of receiving them via SMS unpleasant. Instead of my phone acting like a hyper-active personal assistant squealing with delight every time a new message arrived, I wanted something more like ... a mood ring.

It would be silent, except for maybe the option to vibrate and instead of conventional system notifications it would just hover a great big number over the idle screen indicating the number of unread messages. Okay, that's a half-truth if there ever was one : I did add the big floating numbers but that was as much to act as an indicator that the phone's operating system hadn't silently terminated my application.

Since then I've grown fond of the big numbers on their own merits. What I'd really like is to fill the idle screen — when the phone is, uh, idle — with those big numbers.

Possibly ambient.

I wrote a Growl enabled version, using the Twitter API, mostly as an afterthough because it seemed like a neat trick and it was an additional 4-5 lines of code.

I never got very far with it. The actual interface for reading the messages was crude at best and I had spent most of my time thinking about and then building the floating numbers. It was also during a period when the Twitter API itself was pretty flakey so the messages I did receive always seemed strangely out of sync with reality. It was also around the time the mobile version of the site went live and, experience porn aside, that ultimately proved less demanding to use.

As for the desktop version, it suffered from the same problem that plagues feed aggregators : keeping track of what has or hasn't been seen. Not a hard problem but it's an extra bit of complexity (remember, I was also trying to write an underlying layer of code that would continue to work on my phone...) that makes you wonder whether you couldn't be doing something more fun with your time. I also tend to work on a variety of different computers and the nuisance of doing the magic sync dance between them, so that I don't always seen the same 25 notifications everytime I log in to a different computer, finally answered the question for me.

ZOMG! IM IN UR CLOUD CRYIN UR TEARZ!!!!

Did I mention that I was hungover and I was smitten, once again, with the idea of little, well-behaved messages hovering on the periphery?

I often work in the kitchen when I'm at home and what what I've wanted for a long time was a sexy hecklebot, hanging over the counter, that could talk to all the various APIs out there and show me what's going on in a world that consists only of my friends.

There's a reasonable argument to make that this is what services like Facebook do but since I hate Facebook it's not.

This has always been my attraction to the RedPost/Kit digital frame which does something like this already for Flickr feeds. Maybe still but I wasn't about to get one that afternoon so I continued to sit and stare at my laptop.

There was no blinding flash of insight or anything.

I had already resigned myself to the constaints that Growl imposes on its notification windows : icons are a fixed size; there is no (easy) way to define custom callbacks when a message window is clicked and no way to render or format messages as anything but plain text. The only issue was how to deal with keeping track of messages across multiple computers. I had decided to build myself a notification system for Flickr events.

Or, in the English people who aren’t venture capitalists use, I don’t kill my own chicken for Sunday dinner anymore, why should I provision my own server?

Jacob Harris

I don't actually agree with the underlying argument that's being made there but it does nicely sum up the part where in order to do anything across multiple computers you need something that looks like a database (even if it's just a list of unique identifiers) and then some sort of web interface and then a security model and then all the other crushingly boring details just so you can say : 26452625141 = 1.

It's possible that my reluctance to use any of the web services (AWS) that Amazon has been releasing over the years has been motivated more by ph33r rather than reason but I've never completely understood what or why they were getting at by offering any of this stuff so I've kept to the sidelines and watched.

I have already used del.icio.us and Stikkit as floating databases for other projects but using either to store nothing more than a boolean value or a timestamp seemed about as classy as asking Flickr to store text files.

Even the still nascent DWIMD^H^H^HSimpleDB (which will probably do more to advance the ideas behind the Semantic Web than all the articles TBL could write on the subject in a lifetime) is overkill, though it might be sort of interesting to go back and build a day-by-day scrapbook of notifications.

But I digress. I decided to bite the bullet and try S3.

ZOMG!!! MOUTHFACE FULL OF WORDZ!!!!!

Instead of reading or writing a flag to a local database, the code fetches or creates a web page whose URL contains that flag. Pedants will tell you that is to : GET or POST a resource on the Internet; which is also why they're a bunch of tiresome doorknobs.

This has the advantage of being both portable and fantastically easy as well as flexible since the thing at the end of the URL is, ultimately, just a text file that we can append stuff to ad nauseam (or up to 5GB if you are a tiresome doorknob).

And is costing me both cash dollars and some amount of privacy.

S3 is a billable service and Amazon is a big centralized for-profit company with a penchant for data-mining. I have yet to get my first bill but between local caching, the relatively tiny rates of data transfer I am doing and the quick-look-over-here truly micro-payments schedule that Amazon has put in place I figure it's worth trying until my next credit card bill arrives.

The privacy thing is stickier and I remain skeptical about putting anything I really care about in Amazon's cloud. In principle, the things I'm looking at on Flickr could come back to haunt me but my gut tells me that there's nothing I wouldn't freely admit to and if I really feel like that's a plausible risk, today, we're already fucked. Plus I am hashing the keys for every event notification.

Then I remembered that this entire exercise was about active notifications and not building an answering machine in the cloud :

$> python ./bin/flickr/flgrowler/flcontacts.py -c flgrowler.cfg

[Thu Dec 20 21:44:58 2007][flcontacts] sleep for 120 seconds
[Thu Dec 20 21:47:13 2007][flcontacts] can not find beaconing device, skipping
[Thu Dec 20 21:47:13 2007][flcontacts] sleep for 120 seconds
[Thu Dec 20 21:49:28 2007][flcontacts] 0a:18:42:b8:30:4a is nearby
[Thu Dec 20 21:49:40 2007][flcontacts] received 17 new events (50 total)
[Thu Dec 20 21:49:58 2007][flcontacts] sleep for 120 seconds

(If blog posts had code-names (we would be doomed) then this one would be : To Timo, with love.)

I have given the near-field communication people a hard time over the years mostly because some of the creepier privacy and security issues are waved away with Dubya-like assurances of technological advances that do not inspire confidence, but even I can see the potential. I just think — hope — that after it's baked for a while it will be more ... yes, serendipitous in nature than utilitarian or a tool for discovering the nearest fucking Starbucks.

A couple of the projects at the UK Hack Day event, in London this summer, were built performing magic with the Bluetooth network but when they got up to demo there were so many Bluetooth devices in the audience that the software was crushed under the weight of the possibilities.

Anyway, if two machines are running event listeners simultaneously — each reading and writing to the S3 cloud — and you don't happen to be in front of the one that receives an event first you'll never see it since by the time the second computer finds out about it it will have been marked as seen.

So, accepting the truism that people generally keep their phon... I mean, their devices nearby (enough), this is how we handle the problem :

  1. Start the application or wake up from a previous cycle.
  2. If the config file has a list of Bluetooth devices :
    • First check to see we have the address of a previously seen device and explicitly request the device name
    • If not, or the operation fails, perform a general query of devices nearby, and look for a match with the list defined in the config file.
    • If present, store it in memory so that we don't (necessarily) need to do a broad poll on the next pass. This may just be a function of my not understanding how the PyObjC Bluetooth bindings work but in casual testing a broad find devices query would often time out without necessarily getting to a known-good device. So this is just easier.
    • Also, I know about and love the Lightblue Python Bluetooth bindings but if you call the finddevices method a second time before the first instance has completed it will make your CPU cry. Talking to the Bluetooth frameworks directly is easier which should tell you something given how bent programming in Objective C is...
  3. Open the datastore.
    • If the config defines the datastore as an AWS S3 bucket then the application will reach out across the network and ask AWS for a list of all the buckets associated with the access key defined in the config file. If the bucket described in the s3_bucket_prefix config is not present it will be created.
  4. Fetch and parse a list of events via the Flickr API. Events is just fancy-talk for a list of results for a question you've asked Flickr : What sort of activity has there been on my photostream? What photos has this user favourited? And so on
  5. For each item returned generate a unique identifier and check to see if there is a corresponding key in the datastore. If there is, the item is considered as having already been seen and is skipped.
    • If the config defines the datastore as an AWS S3 then the application will reach out across the network to see if there is an actual thing on the Internet that can be addressed with the UID.
  6. For any remaining items, the application will build a custom message, fetch a thumbnail for the corresponding photo and issue a notification request to the Growl daemon.
    • At the moment thumbnails are stored in what your operating system thinks is its temporary directory. There is currently no attempt to clean up old images. That, along with a user-defined directory in which to store thumbnails, will be added in future releases.
  7. Add an entry for the unique identifier in the datastore. If the identifier is the key in the datastore then the value is the current time formatted as a Unix timestamp.
    • If the config defines the datastore as an AWS S3 then the application will reach out across the network and create a resource on the Internet that can be addressed with the UID.
  8. Sleep for (n) seconds as defined in the application's config file.

In the end it looks something like this :

ZOMG!!! NO BUKKAKE IN UR CLOUD!!!! FAIL!!!!!!

There are three event listeners, so far :

  1. flactivity, which polls the flickr.activity.userPhotos API method for any new activity on your photos in the last two days.
  2. flcontacts, which polls the flickr.photos.getContactsPhotos API methods for new photos from your contacts.
  3. flavourites, which polls the flickr.favorites.getList API method for newly favourited photos from a pre-defined (in a config file) list of your contacts.

The core event listener functionality will shortly be packaged as a separate library so that I can write a Dopplr agent, finally rewrite the Twitter version and then whatever else comes to mind.

Aside from the limits in functionality imposed by Growl itself there are two immediate concerns I'd like to address next :

The first is what to do about window spam after you've been away from your computer for a while. When I sit down at my laptop in the morning the first pass of the newly active listeners will tile my entire screen with event windows. I have taken to scanning them quickly and then just restarting Growl since clicking on each window, to close it, is really boring. Perhaps, the easiest thing to do would be to create a digest of all activity older than, say, an hour and display it as a single notification...

The second issue won't be an problem until I work up the courage to port all of this to Series60 Python but when I do the NFC beaconing code will need to be rewritten to check not only that a given device is within range to display events but also to stop displaying events if another device is within range. That way, you could receive notifications on your phone while you're out and about and then have them switch your computer when you get home.

Or, more likely, have notifications automatically disabled whenever your boss gets within 32 feet...

ZOMG!!! I R NOT LOLCOLORZ!!! BUCKET FULL OF FREEDOM!!!!!

Finally. I still find the whole river of dashboard metaphor, in which I would include the Growl-y bits I've been working on, mostly boring.

I use a feed aggregator for anything that could loosely be classified as news and lifestyle porn and it works great. I even use it to find out when people I actually care about have posted something to their weblog but I absolutely hate it for reading what they've written. Maybe I am the hold-out but I still value the web for the time and effort and consideration that a person puts in to their web pages and I think that gives whatever they are talking about context.

If I want to be notified at all of when something new has happened, I would like a way to feel the (proverbial) elephant rather than have it join me at the table. It's a bit vague, obviously, but there's got to be something more interesting — more fun — than the way we recycle everything as slices of 99 cent pizza, today.

You'd be forgiven if your bullshit detectors are ringing right now because it's definitely a bit pie-in-the-sky. What little I am sure of is that I don't enjoy the way we leave markers in the forest of songlines that the Internet has become and that there's room for a little more art in it all (and maybe an overdue appreciation of Josef Albers) because that is what relationships are made of.

So, yeah. Big floating number friends : flgrowler.py 1.0 and beyond.

ZOMG!! IM IN UR INTENT RUNNIN FROM UR INTERPRETIN!!!!

Update.

Not long after this piece was first posted Adam Greenfield found it in his referer logs and wrote a frank and biting rejoinder. I mention it, here, because :

  1. Questions about my biases aside, he makes a compelling argument and has a point.
  2. I wouldn't change anything I wrote. Or, put another way :
    From : Aaron Straup Cope
    To : Adam Greenfield
    Subject : point taken
    
    If there was intent, vis-a-vis the ratio of male to female pointers, in that
    post then it certainly wasn't conscious.
    
    As for the bit with the bukkake, there's really nothing to read into
    that. Really. Bad taste? Perhaps. I can live with that.
    
    If someone wants to read anything more than me making a silly joke about the
    underwhelming nature of the post -- which was really a ridiculous amount of
    background leading up to some pretty Spartan code -- then I'll meet them at the
    bar because we'll have an argument to work through.
    
    But, point taken.
    
    Cheers, 

The only part that I will take exception to is the pithy comment about the del.icio.us-style links at the top of these pages.

They are, in fact, a collection of links that the people in my del.icio.us network have posted, pulled automatically from the page's RSS feed, out of which a new list containing the most recent post per contact is generated. If that list happened to contain a perceiv^H^H^Hambient gender bias on the day that Adam came by, then ... I guess I blame Joshua.

I expect that we'll see more misunderstandings like this, where meaningful intent is confused with the automated faceting of a person's presence on the Network, going forward.

Anyway, if you've made it this far go read what Adam has to say.