Z-Wave and Emacs

I’ve had a 433-MHz-based “home automation” system (i.e., light switches) for quite some time. It works kinda OK. That is, I’m able to switch the lights on and off, which is the main point.

But, man, the range of 433MHz devices sucks, including all Telldus models. I’ve been able to overcome the problems by having transmitters all over the apt, but getting wall-mounted light switches to work with any kind of reliability has proven impossible.

The problem is that the protocol is just inherently unreliable: It just sends commands out into the ether, and doesn’t have any replay logic or ACKs going on.

But there’s newer (but also old) tech available, and 433MHz devices are disappearing from the stores, and the winning protocol is Z-Wave.

So I got a Z-Stick:

It’s a nice device: You plug it in and it shows up as either /tty/USBx or /tty/ACMx (depending on the model, but it makes no difference), and you talk to it by squirting some bytes at it.

I had expected the protocol to be really well-defined and open, but it’s a proprietary protocol that people have been reverse-engineering for years, which led me to believe that there surely would be a nice repository somewhere that describes the protocol in detail, and has, say, an XML file that describes all the different network packages.

Nope.

But after some googling I found this gist that at least let me check whether I can talk to the device…

… and it works!

It turns out that the Z-Wave protocol is kinda nice. Each package has a checksum, and devices retransmit commands a few times unless they get an ACK, and Z-Wave plugged-in devices (like outlets) work as repeaters, so the Z-Wave network works as a mesh. It’s kinda cool.

There’s a ton of software to control these devices, but using something like Open HAB is just so… end userish.

Instead I wanted to just plug it into my existing Emacs-based system so that I don’t have to, like, use software. Software sucks.

If no machine-parseable spec is available, at least there must be some other sensible software out there that I can just crib implementation details from, right? So I binged “z-wave python”.

And just found Python OpenZwave, which turns out to be nothing but a wrapper around OpenZWave, which is a C++ library.

Whyyy.

It’s a simple protocol, really. You just read from a serial device and then squirt some bytes at the device. It’s not like you need to do Fourier realtime transforms on a vast byte stream or anything.

But who am I to criticise people for choosing odd programming languages to implement their free software? Since it’s C++, at least probably they created some kind of over-engineered monster where you have some XML files that define the protocol, and then they create objects from the stream and use a lot of polymorphism that’ll make the control flow impossible to follow (according to the “everything happens somewhere else” object oriented methodology), but that’s good, because I can just use the protocol definition files and ignore the rest.

Right?

Right?!?

No, the main work flow is based on nested if statements with lots of “switch( _data[1] )”. But surely after that they’ll parse the protocol packages into something sensible?

*sigh*

Well, at least they used variable names that’s understandable. But what’s data[4] and data[6]?

*sigh*

I”M SORRY! THIS IS…

Ok, again, I have no business giving a code critique of this library written by, I’m sure, very nice people and put on the intertubes for the world to peruse and use, and despite being written in the “least information density per pixel displayed” style, it’s clear and easy to follow, and has an impressive amount of comments. It’s still all kinds of wrong.

Perhaps it’s just coming from a different culture? It’s Windows-style programming?

I don’t know, but anyway, with the guidance from this excellent piece of, er, software, I was able to make Emacs parse and execute commands when I touch a wall switch.

And Z-Wave works! Where a couple my light switches were a bit hit and miss before, they now work with 100% reliability over the last week.

I don’t have any Z-Wave outlets yet, so I haven’t bothered to implement sending commands to devices, but I’m sure I’ll have to implement that at some point. But as far as I can tell, that should be pretty straight-forward. I foresee a lot of “but what’s _data[7]?” in my future.

Somebody should still create a Z-Wave repo with protocol definitions, especially since it’s now an open-ish standard. But only as PDFs, of course.

[Edit: I should have googled a bit more, because it pretty much looks like everything I wondered about is in the OpenHAB distribution, which is in Java and has more XML protocol definition files than you can shake a stick at. Well done, Java peeps.]

Nails and Hammers

You know that old saying about gravitating to your favourite tool? Well, my go-to thing for compositing text on top of images (and stuff) was LaTeX, and I’ve been doing that for decades.

What I’m mostly using this stuff for these days is the extremely important task of displaying weather data on small, cheap USB-powered monitors that I have here and there around the apt.

For instance, in the hall I have something that plays a random-but-related youtube clip (with no audio, of course) of whatever’s playing on the stereo, and on top of that I have a LaTeX-generated overlay that says what temperature it is and the rain forecast over the next 24 hours (that’s the line; rain ahoy).

It’s composed by this Perl script that uses LaTeX to generate the clock and the temperature text, curl to download the weather data, gnuplot to make the nice line, ghostscript to make a .pnm file, and som pbmplus things to composite it all.

And what occurred to me the other night is that I wanted to have a tiny text at the bottom there that told me the name of what was playing to and I thought “that’s just so much work”, and then I started wondering whether I should just rewrite all this in Emacs Lisp and use my new favourite hammer: svg.el.

Presto! Still rainy!

It’s now a pure-Emacs image compositing thing which I’ve put on Microsoft Github if you want to read it, but it’s not generally useful. But you could perhaps use a couple of the elements if you want to do something similar.  I also finally got a reason to play with xelb/xcb, which I’ve always wondered about.  Seems like a very nice library, and maps 1:1 the X concepts onto Emacs Lisp.

Compositing images via svg.el is fun!

One thing that I thing I’m going to expand upon and put into Emacs is the SVG path/bezier curve stuff, because I think that would be generally useful.

This bug report adds a new function, svg-path, but I think Eli’s objections are right. Instead of adding such a low-level function, instead we should have, like (svg-multi-line svg points :type ‘bezier :smooth 0.2) that would compute the boring Bezier stuff for you. SVG supports insanely complicated paths, but I don’t think that’s all that useful in general…

But I don’t have time to do implement that properly now, but perhaps sometime this winter…

Oh, and while implementing this, I miscomputed the font size for one of the displays (that just displays what’s playing), and I thought it was such a striking mistake that I kept it.

IMDB in Emacs; or, Honey, I Made an ORM

I’ve always been frustrated by the IMDB web pages. Usually when I’m looking at a director’s oeuvre, I’m not interested in all the shorts, videos and games the director has created, but just want a list of the movies.

When I’m looking at a specific movie, it’s often because I want to know who the character on the screen I’m watching is being played by, but the images are so tiny and low res that it’s impossible to guess who’s who.

And once I found myself wondering, “what’s the name of that actor that played in that film with her and her”, and I know who the latter two are, but not what film, so it would be nice to be able to do a cross reference kind of thing… right? RIGHT!?

OK, the last thing happened only once, but it was still something that I thought might perhaps have been vaguely useful. But, of course, I didn’t do anything about all this because well you know.

I did download the IMDB data set and do various things with it (but mostly based on grepping and ad-hoc searches), but that came to a complete stop when IMDB revamped their data exports. Instead of semi-human semi-readable files, it’s now basically a database dump. No longer can you just grep for “Isaach De Bankolé”, because in the new files, you first have to find his ID, and then you can grep for that, but that just gives you movie IDs, and…

Long story short, I made an Emacs mode for looking at the new-format data.

It’s based on this sqlite3 module for Emacs. My first attempt was based on just storing all the data in hash tables in Emacs, because I’ve got lots of RAM. I thought that since I routinely open multi-gigabyte buffers in Emacs, and that’s no problem, and at work, I routinely have multi-tens-of-gigabyte processes in Common Lisp servers, that should be no problem in Emacs either.

I had forgotten that Emacs’ garbage collector is, er, kinda primitive. It’s an old-style stop-and-copy collector. This is fine for huge buffers, because that’s basically just a handful of objects, no matter how large the buffer is. When you create a 200M element hash table, all those elements need to be mark-and-sweeped individually, and as I found halfway through implementing it, that makes Emacs pause for like ten minutes at a time.

So scratch that. I went for sqlite3 and I store the data on disk. But interacting directly with the sqlite3 database data is a drag, so I wrote a kind of ORM… well, it’s more of a PRM. Plist-Relational Mapping. Because strong typing is for dweebs.

I mean, professionals.

Anyway, the raw dataset from IMDB is about 3GB. The sqlite3 database is about 7GB, and takes an hour or two to create on my machine. (Before I found out that sqlite3 autocommits by default, I had like two transactions per second. By slapping a transaction around the import, I get a few thousands of inserts per second.)

The module has some bugs, but I’ve sent a pull request, so hopefully it gets fixed.  Or pull down my fork instead, which is here, and you’ll need it to do regexp searches.

If you want to play with this, you need a newish Emacs built with module support, the sqlite3 module, and imdb-mode.el.

And then just eval (imdb-download-and-create) and wait for a few hours.

The PRM works pretty much as you’d expect.

(imdb-select 'movie :mid "tt0090798") 
=> 
((:_type movie 
  :mid "tt0090798" 
  :type "movie" 
  :primary-title "Caravaggio" 
  :original-title "Caravaggio" 
  :adultp "N" 
  :start-year 1986 
  :end-year nil 
  :length 93))

See?

(pp (imdb-select 'crew :mid "tt0090798") (current-buffer)) 
((:_type crew :mid "tt0090798" :pid "nm0147599" :category "writer") 
 (:_type crew :mid "tt0090798" :pid "nm0413897" :category "writer") 
 (:_type crew :mid "tt0090798" :pid "nm0418746" :category "director") 
 (:_type crew :mid "tt0090798" :pid "nm0418746" :category "writer"))

Easy!

(imdb-select 'person :pid "nm0147599") 
=>
((:_type person 
  :pid "nm0147599" 
  :primary-name "Suso Cecchi D'Amico" 
  :birth-year 1914 
  :death-year 2010))

Anyway, that’s the low-level interface. Here’s what the user interface looks like:

And then “x” and the noise is gone!!!

Only the real movies! *gasp* It cannot be!

(I didn’t choose Fincher here because I like his films, but because he’s done so much junk that’s it’s impossible to use his IMDB page.)

But… when looking at some actors I knew pretty well, I soon noticed that not all the films that the actor appeared in were listed. Here’s Tilda Swinton most recent few years:

What’s going on?! No Doctor Strange? Could there be a bug in my code? That seems impossible? I mean, it’s my code!

But nope, the problem is with the IMDB dataset. The file that lists what films actors appear in, “title.principals.tsv”, isn’t a complete list of participants, but instead, as the name really sorta kinda implies, a list of the most important people in that film. That means that it lists directors, writers, the cinematographer, (some) producers and then a few actors. But never more than ten people per film.

This is really weird, because directors and writers are already in the “title.crew.tsv” file.

This made me sad until I realised that I could just resort to web scraping.

So now I use the data set as a base and then insert the missing things afterwards.

Doctor Strange!

And when I’ve resorted to web scraping for that, I can just scrape for actor images, too:

*sigh*

In short, IMDB doesn’t have a usable API, and IMDB no longer export enough data to do anything useful with that data. So I guess this Emacs mode will work until they tweak their HTML.

While implementing the scraping, IMDB suddenly went missing and I just got:

I then found out that I had er slightly miswritten the end of the recursion, so I was hitting imdb.com with dozens of invalid hits per second in several concurrent threads.  I AM SORRY IMDB.

They unblocked me after an hour.

Here’s what it looks like in action:

(Click on the embiggen symbol to embiggen so that you can see what’s going on.)

I’m like, selecting a few things and then toggling what bits to see (acting/directing/all/shorts).

Exciting!

And now it’s feature complete, too, so I’ve definitely saved a lot of time by writing this.

Er…  Oh, yeah.  I was going to implement intersections (i.e., list movies that have several specific people involved.  So let’s see which films Tilda Swinton did with Luca Guadagnino:

Easy peasy.  Or the more complete, unfiltered version:

Heh.  I think “Dias de cine” and stuff are just Italian long-running movie news shows that both of them have appeared on?  Or in the same episode?  Hm…  probably the latter, because each TV episode has its own unique ID.

 

Innovations in Emacs Touch Interfacing

I’ve long attempted to hack some touch interfaces for laptops in non-keyboard configurations.

The sad thing is that there aren’t really any good solutions in GNU/Linux. If you want to be able to respond to more complex events like “two finger drag”, you have to hack GTK and use Touchégg, and then it turns out that doesn’t really work on Wayland, and then most of the events disappeared from the X driver, and then…

In short, the situation is still a mess. And then my lug-around-the-apt-while-washing-TV-laptop died (ish), so I had to get a new one (a Lenovo X1 Yoga (2nd gen (which I had to buy from Australia, because nobody would sell it with the specs I wanted (i.e., LTE modem if I wanted to also take it travelling (the 3rd gen has an LTE modem that’s not supported by Linux))))):

And now, with Ubuntu 18.04, everything is even worse, and I’m not able to get any multi finger events at all! All the touch events are just translated into mouse events! Aaaargh!

After despairing for an eternity (OK, half a day), I remembered another touch interface that I quite like: The Perfect Reader.

It’s a bit hard to tell here, but the idea is that you divide the screen into areas, and then you just tap one of the areas to have the associated action happen.

Surely even Linux can’t have fucked up something so basic: It must be possible to get that kind of access.

And it’s possible! Behold!

Er… What’s going on on the other side of the backyard?

Eeek! Kitten! Go back inside!

That’s not a safe place to play! … *phew* It sat down, and turned around and went back inside. *heart attack averted*

ANYWAY!

The idea is that there’s one action grid overlay when Emacs is in the forefront, and another when the mpv video player is.  All the events go via Emacs, though, which controls mpv via the mpv socket interface.  (And, by the way, I have to say that I’m really impressed with mpv.  It has all the commands you want it to have.  The documentation is somewhat lacking, though.)

Here’s a demo:

Basically, I’m just reading the output from libinput-debug-events (which outputs everything that goes through /dev/input/event* (so you have to add your user to the input group to access them)), and then execute things based on that. libinput is allegedly the new hotness, and replaces libev and the synaptics X driver, and is supposed to be supported on both Wayland and Xorg, so hopefully this attempt at an interface will last a bit longer than the previous ones.

I wrote the controlling thing in Emacs, of course, and you can find it on Github. I’ve been using an Emacs-based movie/TV viewer since 2004, and I’m not giving up now! So there.

Flashair, Emacs and Me

My blogging methodology is that I 1) open an Emacs Message buffer, write stuff, and then 2) take pictures of stuff (mostly comics), wanting to have those images appear right where I’m typing. This is a solved issued with Flashair, PyFlashAero and watch-directory.el, but I thought that it sucked that there were so many moving parts.

And besides, PyFlashAero didn’t always do the right thing, and you have to specify so much stuff…

So I wanted to bring it all into Emacs for less fuss. You know this makes sense.

I had a third generation Toshiba Flashair card (W-03), and the problem is that it’s just too slow for my approach, which is basically to look into all directories on the card. It’s s-l-o-w. So I gave up in the project. PyFlashAero was written that way for a reason.

Half a year passed, and then I somehow was made aware that Toshiba had launched a new generation of their product, and it promised 3x faster WIFI speeds and a brand new and faster CPU.

So I got a card:

And I would like to say that it was an immediate success, but it definitely wasn’t. I could download the directory indices nice and fast, but whenever I tried to download an image, it stopped after 0 (zero) bytes. So it seemed like that card had a problem reading itself, basically, and would just hang whenever I tried requesting some data from the (exfat) file system on the card.

But! There was a new firmware W4.00.02, and I had W4.00.00. I installed the new firmware, and presto! It is teh work!

Look, I can snap pics of myself here I’m typing this stuff on the couch:

And it appears in the buffer within a second or two after I snap it! It’s a new paradigm! And it’s untouched by filthy unclean Pythonic hands; it’s all pure Emacs.

The range of the Flashair W-04 also seems improved… the old one had to be within a few meters of my laptop for the laptop and the Flashair to be able to communicate whereas the W-04 seems to be able to communicate over, er, more meters. Here, I went out into the hall and snapped a pic and this image was here in this buffer when I got back:

It’s magic!

But when I went to the kitchen and snapped a pic there, nothing showed up here, so it’s not that magical.

Anyway, here’s the Emacs source code.  You probably need a newish Emacs version for it to work.

meme x giffy

The other week I was tinkering with editing GIF animations in Emacs, and then I started wondering: Can this be any more ridiculous?

Yes.

So it’s a mashup of the Emacs meme mode and the new GIF animation code.  I spent most of the time on this wondering whether I could somehow make one or the other a minor mode before giving up and just mashed the code into meme.el, which can be found on Github.

The main challenge here was figuring out how to make this fast enough.  The first naive implementation just created an SVG 25 times a second with all the data in it, and Emacs just isn’t fast enough to print a ~2MB XML structure that often.  (Not to mention when animating bluray screen grabs: The SVG structure is then about 7MB.)

So I cheated and pre-computed the screengrab bits, and then plonked down those bits into the printed XML structure.  Which made it fast enough even for bluray animations on my rather spiffy machine; your mileage may vary.  If your machine is too slow, you may have to pre-downscale the screengrabs the animations are based on.

Exporting to GIF and MP4 is supported if you have ImageMagick “convert” and “ffpmeg” installed.

 

Of course you should be able to make animated GIFs in Emacs

I was wondering what a convenient production process for GIFs from movies would be like, so I hacked my hacked version of mplayer a bit more.  Nothing major, since it already has all the functionality, but it doesn’t group continuous screenshots by name, which makes picking out the animations afterwards awkward.

There’s probably a gazillion GIF editors out there already, but since the things you typically want to do with an animation (trim start/end, adjust speed and how many frames to skip) are kinda trivial, it seemed more convenient to just write a mode in Emacs.  So I did.

It uses the ImageMagick “convert” command to actually stitch the images together in the end after you’ve done the edit, so it’s not a pure Emacs-only solution.

And here’s the result:

I’m sure this is going to turn out to be really useful some day!