Sharing Links Physically
Why should we only share things we like on Facebook, Twitter or by email?
I’ve imagined a fun application with one of these small thermal printers. Although these printers are really Arduino friendly I coded a .Net class to use them directly with a computer. Then, I made a simple Safari extension which allows to print the URL of the current page… with a QR Code, of course!
The width of a paper roll is perfect for this purpose, and giving a piece of paper to share a link might be quite fun.
This extension sends a command to a small server app which is a background service connected to the printer. It’s not perfect, I’ve made it rather quickly, but it works fine.
I used the MessagingToolkit’s QR Code open source library. Ok, let’s have a look at it.
First, go to a new website everyone’s talking about on the Web.
Let’s say you want to share this crazy video with a friend. It’s time to click on the magic button:
And now here is what’s happening in the real world:
Technically, I used my .Net class in a server app. I made my own server standalone executable, coded in C#/Mono. You can find the source code on GitHub.
The core of the Safari extension is some simple javascript (code from openjs.com):
function printqrcode(url)
{
var postURL = "http://localhost:5555/printqrcode"; //That's my server app.
var params = "url="+escape(url);
var http = new XMLHttpRequest();
http.open("POST", postURL, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {//Call a function when the
// state changes.
if(http.readyState == 4 && http.status == 200) {
alert("QR Code printed.");
}
}
http.send(params);
}
As you can see my server application is a restful service which is waiting for the “printqrcode” command. Here is a piece of the C# code :
if (_postParameters.Get("url") != null) {
url = _postParameters.GetValues("url")[0];
if (!MainClass.printerHandler.isPrinting && !(url == null || url == "")) {
//Resets the printer
MainClass.printerHandler.Reset();
MainClass.printerHandler.isPrinting = true;
//Prints QR Code, in one line
printer.PrintImage(new QRHandler(url).GetImage());
System.Threading.Thread.Sleep(1000);
//Formats short URL
if (url.StartsWith("http://",true,CultureInfo.CurrentCulture))
{
url = url.Substring(7); //removes http://
}
if (url.StartsWith("www.",true,CultureInfo.CurrentCulture))
{
url = url.Substring(4); //removes www.
}
url = url.TrimEnd('/'); //removes the trailing slash
if (url.Length > 32) {
url = url.Substring(0,29) + "..."; //shortens to 32 chars
}
printer.SetLineSpacing(0);
printer.LineFeed();
printer.SetAlignCenter();
//Let's print the URL
if (url.Length > 16) {
printer.WriteLine(url); //prints
} else {
//Double width if less than 16 chars long
printer.WriteLine(url,ThermalPrinter.PrintingStyle.DoubleWidth);
}
printer.LineFeed();
printer.LineFeed();
printer.LineFeed();
MainClass.printerHandler.isPrinting = false;
}
}
There are things I can improve, like a configuration file or why not printing images directly from the browser. To be continued…





How hard would it be to make an extension like this for Firefox?
The hard work is done by the standalone executable which runs in the background, independently of your browser.
As you can see there is only one function in the javascript code that does the job. Everything else is Safari integration code. JS/HTML/CSS add-ons are now compatible with Firefox with a bit of porting.
So, I think it may be not that hard.
Wow! Looks great!
When looking at the command set for the mini printer, what instructions were you using to send full sized images to the printer?
Any idea what nH and nL are in the data set?
Thanks!
Thanks!
I used the ‘Print LSB Bitmap’ function. (’18 118′ in decimal)
This function is intended to print full width images. Therefore your image must be 384px wide.
nL and nH are used to tell the printer how many lines to print and this is a 16 bit value.
This value must be split into two bytes: nL are the lowest bits and nH the highest ones.
Here is the code (there’s a lot of ways to do it):
_writeByte((byte)(height & 255)); //height LSB
_writeByte((byte)(height >> 8)); //height MSB
Then you can send bitmap data.