Printing ALL the things!

So, I’ve been planning to embark on a series of projects over the next few weeks/months/time units of my life. It’s midterm season, so instead of studying (what is studying?) I found myself working on these potentially-useless-but-novel projects. In this case, a receipt printer that prints out tweets by the minute. It’s my own version of an occasionally done project, and an idea that I had (but never really pursued) several years ago. My roommate found a post about a similar project on Engadget that was made using an Arduino, and it re-kindled my desire to do it.

Earlier in the week, I had won a thermal printer on Ebay. More specifically, it’s a Zebra LP-2443, commonly used by UPS and people who use UPS to print 4×6 sticky-backed shipping labels. I won it for the bargain price of a little under $13, plus flat-rate shipping. This particular machine features the most high-tech interfaces (heh), RS-232 and IEEE-1284. These are more commonly known as serial and parallel, respectively. Now, while I am the owner of several types of computers, none of them were graced with either of these interfaces. So, I was off to Monoprice.com (one of my favorite shopping sites) where I picked up this little baby: A USB-parallel adapter.

It didn’t advertise any compatibility with Mac OS X or Linux (the platforms that I run), but I bought it anyway, because who can go wrong at the low price of $6? And I didn’t go wrong, because it worked wonderfully.

At first, I attempted to connect the printer to my Mac via a PL2303 USB-Serial adapter, but for some reason I couldn’t manage to get any bits to flow. I suspect it may have had something to do with the fact that I didn’t have any thermal stock besides a bunch of old receipts taped together, which the printer wasn’t very happy with.

Next I moved to the parallel adapter (Above? At left? Who knows where that danged photo went.) with my Mac, and that proved more promising, even with the jank paper. The adapter showed up in the Printer dialog and there was a Zebra EPL2 driver, and I was thrilled. The first time I tried to print something, it printed it with a little delay. Rejoice! I tried it again: Nothing. Well, that sucked.

So, I moved to a Linux machine, an “old” formerly-Vista-laptop my sister gave me. I plugged the adapter in, fired up the printer and the print settings dialog, and whaddyaknow, it saw it and had the very same EPL2 driver as my Mac. I opened Vim, typed “Hello, world.” and sent it to the printer. And I’ll be damned, it printed. I did it again, and it printed again. Holy crap, it was working.

Now, this whole time, my objective was to somehow push tweets to it, but only the most recent unprinted tweets. Now that I was on Linux, I assumed Twidge (a Twitter CLI) would be the answer, and I was right. My initial evaluation of Twidge was that it could just automatically spit out the recent tweets to a file, using a little terminal redirection and the crontab. Then, I would use diff (with more redirection) to compare those tweets to a file containing the tweets that have already been printed. Then I would take that file and process it using a hand-coded (on paper in my math class) C program that I wrote to insert carriage returns after every ~20th character to make it printable. And then print that out. All using cron to automate it.

Seems logical, right? Yes and no. Yes, it’s logical, but it’s grossly unnecessary. After reading the Twidge help file, I learned that it knows which tweets are read and unread and will happily only spit out the unread ones, simply by adding the -su flag to the command. Lovely! Everything I wrote about above is nullified and life is easy again.

I then looked into printing out the output of Twidge. I had expected I would have to redirect it to a file and then print that file. But again, I was wrong. By throwing on a “| lp” to the command, all output was piped (excuse the pun) to the default printer. Lovely. But it’s upside down. No bother, just rotate the output in the printer settings by 180°. Lovely, now they’re right side up. But wait, if there are a lot of tweets, they get disordered because they’re being printed in order but upside down… After reading the lp man page, I came up with a super elegant solution. This time it was to change “| lp” to “| lp -o outputorder=reverse”. That forces the printer to collate the already-rotated pages in reverse order, correcting the issue I was having.

So it works. I edited my crontab to execute that command “twidge lsrecent -su | lp -o outputorder=reverse” once a minute, on the minute, sixty times an hour, etc. for as long as the computer is running. Note to self: Don’t leave it running at night, because it’s loud enough to keep me from falling asleep the night before I have two midterms.

A few footnotes: I bought the thermal rolls at Staples because I needed them and they were the cheapest ones they had, that’s why they’re so narrow (half of the printer’s supported width). I plan to order wider ones online. I gave it it’s own twitter account so it only prints things I care about. Sorry, Engadget, you didn’t make the cut. Also, it kinda formats things jankily at the moment because.. I really don’t quite know why.

Addendum: Since I wrote this post, I determined why things were being formatted funnily. Twidge formats it’s output for the screen with lots of extra spaces and line-breaks, so it was not pretty on the printer. I have since written two little C programs that I pipe the tweets through before hitting the printer to format everything properly and even make appendages to some tweets. I will eventually write these up. The first one, called TweetReplacer, simply reads standard input into an array of a struct I designed to represent each tweet, scans the usernames for my friend’s account, and then adds a (rather inappropriate) hashtag to the end of all his tweets. The next one, called TwitterFormatter, arranges the tweets into a single column of 23-character lines. It’s smart enough to not break words in half when changing lines, too. I’m rather proud of it.

 

Here are some final pictures for good measure.