dan is currently certified at Master level.

Name: Daniel Barlow
Member since: 2000-02-13 22:03:36
Last Login: 2010-01-20 09:38:57

FOAF RDF Share This

Homepage: http://ww.telent.net/

Notes:

I like Common Lisp

  • CLiki - the groupware hypertext free CL projects link farm
  • cirCLe - one man's LispOS fantasy

The diary here is updated infrequently. See http://ww.telent.net/diary/ for geeky stuff, or www.coruskate.net for skating

Projects

Articles Posted by dan

Recent blog entries by dan

Syndication: RSS 2.0

Changing sort order with ActiveRecord find_in_batches

The subject is Googlebait pure and simple, because the short version is that you can’t. The very slightly longer and significantly more defensible version is that you may be able to but they don’t want you to apparently because you might get the wrong answer if you mutate the data as you’re traversing it (and because it’s fast in MySql).

Personally I think the answer there is Well Don’t Do That Then (and who cares about MySql) but that’s just my opinion. If you want to order by, say, created_at descending, and perhaps you want to paginate the results, the only sensible conclusion to draw is that find_in_batches is just not intended for this use.

But it’s not an unreasonable use. So I wrote ar-as-batches which lets you do

Users.where(country_id: 44).order(:joined_at).offset(200).as_batches do |user|
  user.party_all_night!
end

and it all works as you’d expect. I should of course caution you that

  • you might get the wrong answer if you mutate the data as you’re traversing it (so Don’t Do That Then), and that
  • ordering by something other than id ascending may be slower in MySql.

I don’t know whether to be proud or ashamed of the tests , which check the generated queries by assigning a StringIO logger to ActiveRecord::Base.logger and then matching regexps in it after each test runs. There ought to be a better way. Perhaps there is a better way. Don’t know what though.

Syndicated 2012-05-04 06:29:34 from diary at Telent Netowrks

Listening to a Polar Bluetooth HRM in Linux

My new toy, as of last Friday, is a Polar WearLink®+ transmitter with Bluetooth® because I wanted to track my heart rate from Android. Absent some initial glitches which turned out to be due to the battery it was shipped with having almost no charge left, it works pretty well with the open source Google My Tracks application.

But, but. A significant part of my exercise regime consists of riding a stationary bicycle until I feel sick. I do this in the same room as my computer: not only are GPS traces rather uninformative for this activity, but getting satellite coverage in the first place is tricky while indoors. So I thought it would be potentially useful and at least slightly interesting to work out how to access it directly from my desktop.

My first port of call was the source code for My Tracks. Digging into src/com/google/android/apps/mytracks/services/sensors/PolarMessageParser.java we find a helpful comment revealing that, notwithstanding Polar’s ridiculous stance on giving out development info (they don’t, is the summary) the Wearlink packet format is actually quite simple.

 *  Polar Bluetooth Wearlink packet example;
 *   Hdr Len Chk Seq Status HeartRate RRInterval_16-bits
 *    FE  08  F7  06   F1      48          03 64
 *   where; 
 *      Hdr always = 254 (0xFE), 
 *      Chk = 255 - Len
 *      Seq range 0 to 15
 *      Status = Upper nibble may be battery voltage
 *               bit 0 is Beat Detection flag.

While we’re looking at Android for clues, we also find the very useful information in the API docs for BluetoothSocket that “The most common type of Bluetooth socket is RFCOMM, which is the type supported by the Android APIs. RFCOMM is a connection-oriented, streaming transport over Bluetooth. It is also known as the Serial Port Profile (SPP)”. So, all we need to do is figure out how to do the same in Linux

Doing anything with Bluetooth in Linux inevitably turns into an exercise in yak epilation, especially for the kind of retrocomputing grouch (that’s me) who doesn’t have a full GNOME or KDE desktop with all the D buses and applets and stuff that come with it. In this case, I found that XFCE and the Debian blueman package were sufficient to get my bluetooth dongle registered, and to find and pair with the HRM. It also included a natty wizard thing which claimed to be able to create an rfcomm connection in /dev/rfcomm0. I say “claimed” not because it didn’t – it did, so … – but because for no readily apparent reason I could never get more than a single packet from this device without disconnecting, unpairing and repairing. Perhaps there was weird flow control stuff going on or perhaps it was something else, I don’t know, but in any case this is not ideal at 180bpm.

So, time for an alternative approach: thanks to Albert Huang, we find that apparently you can work with rfcomm sockets using actual, y’know, sockets . The rfcomm-client.c example on that we page worked perfectly, modulo the obvious point that sending data to a heart rate monitor strap is a peculiarly pointless endeavour, but really we want to write our code in Ruby not in C. This turns out to be easier than we might expect. Ruby’s socket library wraps the C socket interface sufficently closely that we can use pack to forge sockaddr structures for any protocol the kernel supports, if we know the layout in memory and the values of the constants.

How do we find “the layout in memory and the values of the constants”? With gdb. First we start it

:; gdb rfcomm-client
[...]
(gdb) break 21
Breakpoint 1 at 0x804865e: file rfcomm-client.c, line 21.
(gdb) run
Starting program: /home/dan/rfcomm-client

Breakpoint 1, main (argc=1, argv=0xbffff954) at rfcomm-client.c:22
22          status = connect(s, (struct sockaddr *)&addr, sizeof(addr));

then we check the values of the things

(gdb) print sizeof addr
$2 = 10
(gdb) print addr.rc_family 
$3 = 31
(gdb) p/x addr.rc_bdaddr
$4 = {b = {0xab, 0x89, 0x67, 0x45, 0x23, 0x1}}

then we look at the offsets

(gdb) p/x &addr
$5 = 0xbffff88e
(gdb) p/x &(addr.rc_family)
$6 = 0xbffff88e
(gdb) p/x &(addr.rc_bdaddr)
$7 = 0xbffff890
(gdb) p/x &(addr.rc_channel)
$8 = 0xbffff896

So, overall length 10, rc_family is at offset 0, rc_bdaddr at 2, and rc_channel at 8. And the undocumented (as far as I can see) str2ba function results in the octets of the bluetooth address going right-to-left into memory locations, so that should be easy to replicate in Ruby.

  def connect_bt address_str,channel=1
    bytes=address_str.split(/:/).map {|x| x.to_i(16) }
    s=Socket.new(AF_BLUETOOTH, :STREAM, BTPROTO_RFCOMM)
    sockaddr=[AF_BLUETOOTH,0, *bytes.reverse, channel,0 ].pack("C*")
    s.connect(sockaddr)    
    s
  end

The only thing left to do is the actual decoding. Considerations here are that we need to deal with short reads and that the start of a packet may not be at the start of the buffer we get – so we keep reading buffers and catenating them until decode says it’s found a packet, then we start again from where decode says the end of the packet should be. Because this logic is slightly complicated we wrap it in an Enumerator so that our caller gets one packet only each and every time they call Enumerator#next

The complete example code is at https://gist.github.com/2500413 and the licence is “do what you like with it”. What I will like to do with it is (1) log the data, (2) put up a window in the middle of the display showing my instantaneous heart rate and zone so that I know if I’m trying, (3) later, do some interesting graphing and analysis stuff. But your mileage may vary.

Syndicated 2012-05-03 21:10:29 from diary at Telent Netowrks

Sharpening the sawfish

My son is two weeks old today. I don’t usually go a bundle on putting personal info on the public web – I keep that for Facebook, where they at least pretend to keep it private for me - but I mention this to explain why I’m using my laptop a lot more than my desktop lately.

The problem with my laptop is the mouse pointer. It’s one of those pointing stick devices technically known (apparently) as an isometric joystick and more commonly known as a nipple , and when the room is warm the little rubber cap gets slippery very quickly. So I decided to invest a little time in a few keyboard shortcuts.

As an Emacs user I know I’m supposed to like tiling window managers, but I don’t. My editor windows are windows onto text files that may be any size and shape but in which it’s a fairly safe bet (see “locality of reference”) that the spot I want to edit next is usually spatially close to the spot I’m currently looking at. The other ‘windows’ on my screen are things like web browsers and GUI programs where there’s no such guarantee, and the only way to make them work is to allow them to take the size and shape that their authors wanted them to have. So after a brief experiment with awesome I punted it and went looking for a programable window manager that was designed for overlapping windows.

And ended up back with Sawfish, which I used to use back when it was fashionable. Sawfish customization is a two-phase process: first you write commands in Lisp, then you use the sawfish-ui program to assign them to keystrokes. A bit like Emacs, really, and perhaps not surprisingly.

First I needed some shortcuts to focus particular windows (Emacs, Firefox, xterms). Happily, someone has done the work for this already: I just had to download the Gimme script and set up bindings for it

Then I needed something to chuck windows around the screen. The requirement is pretty simple here: every window on my screen is aligned against an edge, so I just need commands to pan a window to each edge. Here is the finished script in which the points I would like to draw attention to are

  • I use focus-follows-mouse mode, or whatever it’s called these days. This means that if I move a window under the pointer I need to move the pointer too otherwise it will go out of focus. The warp-cursor-to-window function does this: I needed to calculate the pointer position relative to window, which for some reason isn’t a builtin.
  • window-frame-dimensions is window-dimensions plus the decorations. We need these dimenstions for throwing windows rightwards or downwards, otherwise they end up slightly offscreen.
  • define-command is the magic that makes our new functions show up in the sawfish-ui dialog. The "%f" sigil means to pass the current window into the function.

And that’s about it. Put the file somewhere that sawfish will find it – for me, ~/.sawfish/lisp seems to be a good place – add the lines

(require 'gimme)
(setq warp-to-window-enabled t)
(require 'throw-window)

to .sawfishrc, and then set up your keys in sawfish-ui. I assigned them to Windows-key shortcuts: at last, I have a use for the Windows key.

If you hadn’t spotted in amongst all that, I have githubbed my dotfiles. More for my convenience than for your edification, but feel free to rummage. If you are one of the three other remaining XTerm users, have a look at the XTerm*VT100*translations in my .Xdefaults - I stole that “press Shift+RET to background the command” trick from Malcolm Beattie nearly twenty years ago and have been using it ever since.

Syndicated 2012-02-22 20:25:20 from diary at Telent Netowrks

ANN Twitling: a Twitter link digest tool

Problem: I can’t keep up with the Internet

I often check Twitter on my phone. When I see tweets with links in them I tend to skip over them intending to return later when I’m on a computer with a full-size screen, and then forget about them either because I find something else to look at or I can’t be bothered with scrolling all the way down again. And looking through old tweets is nearly as bad on the full-size twitter web site as it is in a mobile client.

Proposed solution: I need a computer program to read the Internet for me

Thus, Twitling: a small script consisting of Ruby and Sinatra and OmniAuth and the Twitter gem and Typhoeus to grab links in parallel, the function of which is to read one’s timeline and display the resolved URL, the title and an excerpt from the text of each link that was posted. Source code is on Github.

I haven’t really used it myself yet in anger: the first thing I notice while testing it is that there are a whole lot more links in my feed than I thought there were, and the original plan to produce a 24 hour digest might become very unwieldy.

Possible further development ideas include

  • speed it up, by prefetching, better caching, or fetching the links asynchronously and client-side
  • an “older” link at the bottom of the page
  • Atom/RSS output so it gets fed to me every so often and I don’t have to remember to check it
  • email output (for the same reason)
  • some css gradient fills just to make it look modern (hey, I already used text-shadow, what do you want, round button borders?)
  • your suggestion here: email dan@telent.net or open an issue on Github. Bug reports too.

Try not to break it, please.

Syndicated 2012-02-01 12:54:57 from diary at Telent Netowrks

backbone.js 1 0 jQuery

I’ve spent a few hours over the last couple of days figuring out how to use backbone.js, and so far I’m impressed by it: it solves a real problem elegantly and doesn’t seem to have an entire religion bolted onto the side of it.

5 minute summary: it introduces models (and collections of them) and views to client-side javascript, and connects them with a publish/subscribe event notifier system so that when you make changes to a model all the views of it update without your having to remember to do anything to them.

A Model is an object that knows how to update itself from a Rails-y “REST” server (scare quotes, because as we all know these days REST isn’t what you think it is ), and publishes its attributes using the methods set and get.

	var m=find_me_a_model();
	var selected= (m.has('selected')) ? m.get('selected') : false;
	m.set({selected:  !selected});

Calling set will, if the value has changed, trigger a changed event handler to be called in all objects which have bound to it. These objects are usually Views.

A View is an object with a render method and an el attribute, and in which calling the former creates a piece of DOM tree in the latter, which you can then attach to your document somewhere

MyApp.Views.ThingView=Backbone.View.extend({
    initialize: function() {
	this.model.bind("all",this.render,this);
	this.render();
    },
    // ... this is not working code - I missed out some important bits ...
    events: {
	"click li" : "do_select",
    },
    do_select: function(e) { ... },
    render: function() {
	var ul=$(this.el);
	ul.html(some_html_for(this.model));
        return this;
    }
})

jQuery(document).ready(function() {
     var myView=new MyApp.Views.ThingView();
     $('#some_element').append(myView.render().el);
});

Collections are provided too. They come with a large number of iteration functions (map, filter, reduce, all that stuff) which makes them really rather useful, and you can build Views of them in much the same way as you can build views of models.

(To complete the completion, there’s also a Router, which is an interface for monkeying around with the URL so you can build bookmarkable client-side apps. But I haven’t had to use that yet)

Anyway. As you see in the example above, the view can also take a hash of events which is registered with jQuery using its delegate method. In this case we’re asking to have do_select called whenever a click event is received on any li element inside it. Great!

Not so great when it unexpectedly doesn’t work, though. Specifically, jQuery drag/drop events don’t work with jQuery’s delegate method, and there’s nothing in the documentation on either page to stop you wasting an afternoon finding this out. Way to go. For more details on just how much hysterical raisins mess is involved with jQuery event handlers, see the pages for on and live – look upon these works, ye mighty, and despair.

backbone.js is here. There’s a Ruby gem for using it with Rails: add rails-backbone to your Gemfile, and you get a handy set of generators which write Coffeescript for you. (A brief inspection of the result says that this is a good thing because there’s no way on earth I’d want to write that stuff myself. But I concede, significant whitespace is a valid personal preference, just not one of mine.)

Syndicated 2012-01-29 22:04:06 from diary at Telent Netowrks

158 older entries...

 

dan certified others as follows:

  • dan certified mjc as Journeyer
  • dan certified mjs as Journeyer
  • dan certified alex as Journeyer
  • dan certified nwv as Journeyer
  • dan certified argent as Master
  • dan certified ariel as Master
  • dan certified Ward as Master
  • dan certified Sunir as Journeyer
  • dan certified wnewman as Master
  • dan certified pvaneynd as Master
  • dan certified Omnifarious as Journeyer
  • dan certified kira as Journeyer
  • dan certified tbmoore as Master
  • dan certified fufie as Journeyer
  • dan certified ingvar as Journeyer
  • dan certified rjain as Journeyer
  • dan certified walters as Journeyer
  • dan certified crhodes as Master
  • dan certified rvdm as Journeyer
  • dan certified slef as Apprentice
  • dan certified hands as Master
  • dan certified mdanish as Journeyer
  • dan certified bmastenbrook as Journeyer
  • dan certified tagishandy as Journeyer

Others have certified dan as follows:

  • dria certified dan as Master
  • uzi certified dan as Journeyer
  • riel certified dan as Journeyer
  • andrei certified dan as Journeyer
  • dhd certified dan as Journeyer
  • pp certified dan as Journeyer
  • gbritton certified dan as Master
  • lmb certified dan as Journeyer
  • skyhook certified dan as Journeyer
  • mjs certified dan as Journeyer
  • zhp certified dan as Journeyer
  • dick certified dan as Journeyer
  • ajkroll certified dan as Journeyer
  • jes certified dan as Journeyer
  • dwmw2 certified dan as Journeyer
  • mkp certified dan as Journeyer
  • cmm certified dan as Master
  • Simon certified dan as Journeyer
  • phaedrus certified dan as Journeyer
  • asmodai certified dan as Journeyer
  • ariel certified dan as Master
  • mbit certified dan as Master
  • grahamw certified dan as Master
  • mwh certified dan as Master
  • nixnut certified dan as Journeyer
  • Omnifarious certified dan as Journeyer
  • fufie certified dan as Journeyer
  • manu certified dan as Journeyer
  • rjain certified dan as Journeyer
  • crhodes certified dan as Master
  • walters certified dan as Journeyer
  • davej certified dan as Journeyer
  • jf certified dan as Master
  • rvdm certified dan as Journeyer
  • slef certified dan as Master
  • ks certified dan as Journeyer
  • fxn certified dan as Journeyer
  • ricardo certified dan as Master
  • varjag certified dan as Journeyer
  • chalst certified dan as Master
  • redowl certified dan as Master
  • jeroen certified dan as Journeyer
  • lukeg certified dan as Journeyer
  • mdanish certified dan as Master
  • Stevey certified dan as Master
  • sral certified dan as Master
  • water certified dan as Master
  • nikodemus certified dan as Master
  • alexm certified dan as Journeyer
  • bmastenbrook certified dan as Master
  • badger certified dan as Journeyer
  • cyrus certified dan as Master
  • technik certified dan as Master
  • pcburns certified dan as Master

[ Certification disabled because you're not logged in. ]

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!

X
Share this page