Thursday, December 19, 2013

A Better Cloud Printer II - API interface

This post continues from my earlier post:

The API definition

So I have got my software stack on a drawing board, next is to make it happen with actual code. RestFul API requests are defined in JSON format:

// this is the very 1st API definition, print out something to a remote printer
{
  "sid"         :"asdfasdf",
  "secret"      :"13wd23d2323r",
  "apiversion"  :"2014-01-01",
  "service"     :"submit",
  "parameter"   :{
      "printerid"   :"asdf2323wd2e",
      "title"       :"xxxxxxx",
      "content"     :"xxxxxxx",
      "contentType" :"PLAINTEXT"
  }
}

  // Response
  {
    "jobid" :"xxxx",
    "status":"ok",  // in progress, fail, ...
    "printerid" :"xxxx"
  }
  


Will update the progress soon....

*Edit 2013-12-27

I have been working on this thing during the holiday season. The rough framework code for public API has been setup as follows:

Public facing software stack: Centos + Nginx + PHP + mySQL + GearMan
PHP libraries are:
  • Luracast Restler - the framework handles RESTful requests
  • Idiorm - ActiveRecord library. (When I am too lazy to write real SQL queries)
  • Whole bunch of PHP utility functions I wrote in the past.
Although the rage is all about Redis and Node.js, I don't see a compelling reason to use the newer software stack. Call me old school:
  • Print API data is strictly structured, saved to database as json encoded string.
  • RESTful, no state between requests.
  • The API will return right after been fired.  (before the actual printer output is finished)
  • Client Callback url for job status update.
Why not Redis/Node/Mongo/Riak/Erlang/whatever?  With Nginx + PHP-fpm, this setup should easily handle 100+ requests/sec on a very cheap VPS(by cheap,  I mean $5 per month).  And I don't see it reaching that limit with a deployment of less than 2000 printers.  If I ever run out of server capacity, the fortune is on my side.  I should already be making enough money to upgrade the servers.

For the actual worker process that handles individual request processing, I might consider something runs on top of libev as daemon.  Could be Node.js or Python Twisted, will leave that for later decision.

*Side note: I am thinking about opensource the entire thing on Github, anyone interested?
If someone can help manage the repo, I'll make it happen.


A Better Cloud Printer I

Continue from my last post: Looking for a better cloud receipt printer.

A Better Cloud Printer I

So this is my ideal cloud thermal printer:
  • Small form factor. (takes little desktop space)
  • Connects on Lan/Wifi/3G
  • Easy to use API to print things.
  • Provide server infrastructure at very low recurring charge. (Just like Twilio)
  • And the printer sells for under $100

Cost

My initial thought was to attach a Raspberry Pi to a regular thermal printer.  The total cost would be roughly $100.
  • $50 Thermal printer
  • $40 Raspberry Pi
  • $10 SD card
  • Adding 3G connectivity would require $50 extra 3G dongle
Sounds simple enough, and I got my Raspberry Pi right away from a local electronics store.

However, the search for a $50 thermal printer took me to an unexpected journey. You can read the experiences on my other blog posts. (Post 1),(Post 2).  Long story short, now I have a working Thermal Printer attached to the Raspberry Pi, the rest is software.

Software

Then the problem becomes how to implement a software stack to control printer from remote server.
  • Communication between printer and server
    • All China-made GPRS printers uses some custom TCP Socks protocol.  This requires me to implement all server structure and error checking mechanism.  (Not great)
    • TCP Socks will have problem behind firewall/proxy.(Not great)
    • I favor XMPP protocol for its ability to fallback to HTTP if Socks fail.
    • XMPP servers already implemented off-line message and presence etc.
    • Downside is: XMPP uses more bandwidth than custom TCP Socks.
  • The actual print out
    • This is simple, just issue ESC/POS command to serial port.
  • API interface for issuing printing command, managing printer.
    • The server must have a XMPP master node to oversee all printers.
    • Upon every API request, the master node talks to printer and returns result to caller.
    • API return data in JSON form.
  • Server Software
    • RPi runs archlinux because I wish to use the latest software.
      • Final product should run a more stable distro.
    • Prosody as XMPP server.  Fast, small memory footprint.
    • Nginx/PHP-fpm as web server.
  • Programming landuage
    • It appears that Python has better resources to work on Raspberry Pi as XMPP client.
    • PHP for API, easy to use.  Small resource foot print.

Software II

Upon some initial discovery, the solution lead to even more problems:
  • Gracious shutdown (fixed, Jan 2014)
    • File System corruption. The printer is turned off arbitrarily. However, default Linux filesystems are not designed to handle that. 
    • Need to fit Archlinux onto live-CD or something similar.
    • Also need the client to be able to update itself.  Therefore it takes a little more than live-CD.
  •  XMPP master node (fixed, Jan 2014)
    • At every API request, I need to initialize the master node in PHP.  Is there a way to have a long-running master-node?
    • What if the long-running master-node fails? How do I fail-over to a second node?
    • It is possible for printer to initial the communication when coming online; how do I feedback to the server?
  • Remote Configuration
    • Since the printer is suppose to "just work" for end user, I need something to config the printer's wifi/network remotely.
      • what if I need to config WIFI when the printer is not connected?
These problems are important for a production-ready product, however they do not get in the way of building my very first demo unit.  I will come back and fix them soon.

Next post: A Better Cloud Printer II - API definition





Tuesday, December 17, 2013

Looking for a better cloud receipt printer.

The problem of remote printing

I have been looking for a solution to print out receipt-like stuff remotely, be it online food order or e-commerce shipping request.  As a geek person, I also wish it to be cheap enough to use.  So far I have not had great success in finding such a product/service.

A few promising candidates are:

Little Printer from BERG
Problem:
  • Expensive. I mean, very expensive. 
  • Not durable.  The construction fits for a hobby project, but not shop floor.
This little printer fits the bill except for its price tag.  I don't know about you guys; a little printer retails for $219 plus $40 shipping is insane to me.


     
    SMS/GPRS Printer
    Problem:
    • Need to roll(develop) my own server infrastructure.
    • Requires mobile data plan. (Expensive in Canada)
    This $99 device is almost right for my purpose.  Only it is offered by some Chinese suppliers that I do not have a lot of faith in their software quality.



    E-print, Cloud Print, Epson, HP, Canon
    Problem:
    • Large size. (Don't like a full size laser-jet on the desk.)
    • Printing delivery by email, no API/Service for delivery status.
    • Maintenance issue. (ink, toner, paper jam)




    Google Clould Print
    Problem:
    • Can only use under someone's gmail account.  Not ideal for large number of deployment.
    • Requires computer(or Raspberry Pi).



    Seriously, how difficult it is to make a receipt printer that fits my use case without breaking the bank?
    • Connects on Lan/Wifi (Free if I already have internet)
    • Easy to use API to print things.
    • Provide server infrastructure at very low recurring charge. (Just like Twilio)
    • And the printer sells for under $100


    Please read on...

    A Better Cloud Printer I

    A Better Cloud Printer II - API interface 


    (I will post updates on my own version of cloud receipt printer as it is being developed)

    Review: Generic 5890 thermal receipt printer

    If you ever shopped ebay or amazon for a cheap thermal receipt printer, you must have seen this one offered by an array of sellers.


    Some of them come in slightly different enclosure, but from the specification and placement of buttons etc, you can tell it is the same machine.

    My theory is that, this model 5890 (T-5890, 5890G, FT-5890, etc.) is manufactured by several different manufacturers in China.  They must be based on the same ODM scheme. Another thing in common is that they all comes in brown box and no marking of manufacturer's address or so.  (generic - no brand)

    Hardware

    As usual, I take it apart and see what's inside.
    Very easy to disassemble.


    In case you can't see the marking on IC, it is using:
    - NUVOTON nuc501adnarm
    This is the controller, ARM-M0

    - A3906
    I think this is the motor driver.

    - Winbound 25016BVSIG
    SpiFlash

    * NUVOTON / Winbound is the same company.






    To be fair, this solution isn't bad.  The choice of ARM-M0 and 16mbit ROM is capable of many things.  However, the problem is in the manufacturing part
    • For this particular unit I got, there are components look like scrapped off used electronics and soldering job isn't great.  
    • The power supply which comes with the printer feels flimsy.
    • Compatibility under windows. (I'll get to this below)


    The printer head (JRP-2RA1) has manufacturer's sticker.  It's website states that this printer head is electronically compatible with Fujitsu FTP-628MCL101, which is a popular model used in many thermal receipt printers.

    Software  -  Linux

    Connecting it to a linux machine through USB, it shows up as /dev/usb/lp0.  Since it does not supply Linux driver with the machine, I can not use CUPS.  Just plain old serial connection.

    [root@alarmpi ~]# lsusb
    Bus 001 Device 005: ID 0416:5011 Winbond Electronics Corp. Virtual Com Port
    Bus 001 Device 004: ID 046d:c52b Logitech, Inc. Unifying Receiver
    Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    cat test.txt > /dev/usb/lp0
    
    #For this to work, I have to disable CUPS
    

    The printer comes with ESC/POS manual on a CD. It appears to be compatible with Epson TM-T88, with some exceptions. However, as I tested the unit, some compatible ESC/POS command are only partially supported.
    • ESC ! n     This shorthand setting works, but does not take mixed setting well.  Stick with individual command for safe.
    • Underline does not show in some cases involving line wrapping.
    • Other small differences from EPSON ESC/POS.

    Here is the sample print out:

    Software - Windows 7  (it does not work)

    I can not get it to work on win7.  The device shows up and driver installed without complaint, it just does not print anything.  Anything submitted to the printer shows as error.

    I have tried the following:
    • change printer port USB - LPT - COM
    • re-install printer driver
    • unplug / plug in again
    It shows on my device list. But does not print anything.

    I have only windows 7 at home, therefore can not vouch for XP/Vista/8.  If any reader has success with this printer on windows machine, please share your method.


    Overall

    This is a cheap thermal receipt printer with partial ESC/POS support.  The general concern with these printers are the printer head is not durable.  If working continuously, overheating might reduce printer head's useful life quickly.

    What it does:
    • Print out English/European/Chinese characters, symbols.
    • Basic formatting such as double height, double width, underline.
    • Easy to work on Linux.

    What it doesn't do:
    • Work under Windows 7.
    • Drop-in replace your Epson TM-T20.

    Saturday, December 14, 2013

    BTHT-V6 TTL/RS232 thermal printer module

    Review: BTHT-V6 TTL/RS232 thermal printer module

    In this review, I have two thermal printer modules, as shown below:

    (they both look the same, so I only showed one in the picture)



    Let's call them V6 and V6-simple.  The manufacturer offered different variations inside the same chase(which caused me quite a bit of confusion). The only way to tell their difference is to open the casing and look at the electronics inside.




    This one, I call it the normal V6, has a MAX3232 inside to support RS232 connection.

    It has both TTL and RS232


    The V6-Simple, does not have MAX3232, and the PCB layout is somewhat different.

    It has only TTL connection.

    Looking carefully, the TTL pin layout is different. This has caused me huge trouble when I was trying out the unit.

    It turns out also supports only ANSI character printing.



    Common specs:

    • 2.25"(58mm) paper width (48mm printing width)
    • Max paper roll diameter of 1.5" (39mm)
    • Default 19200bps baud rate
    • 9v~24v 15w power input

    Difference between the two:


    V6 V6-Simple
    ANSI Chars Support Support
    ESC/POS Support -
    Bitmap Support -
    Printer Status Support -
    TTL Support Support
    RS232 Support -

    V6-simple can print only ANSI English characters, that's it. Nothing else.



    Tests:

    I used PL2303 usb-2-TTL cable and MicroRidge ComTest.  If you don't have it, go grab a copy, the software is free.  PL2303 is really cheap on ebay($1.5 shipped).



    Powered by my 12v 5A power supply.  It is really handy to have a few of these around.  If you don't have one, no worry.  Chances are your router/monitor/other small appliace already have a 12v power supply, just use it.

    If using linux, can do something like this to test printer:
    cat file.txt > /dev/ttyS0
    # file.txt must end with a Carriage Return{CR} to output immediately.
    


    Test with V6-Simple:
    There really isn't much to say. Send ASCII characters down the COM port, it prints out.  The printer will auto wrap text at 32 characters.


    Test with V6 (feature rich version):
    This one supports ESC/POS command, however the definition is slightly different from the EPSON TM88. For example, the "batch specify print mode" [ESC !] is not available on V6.

    *Note: Another little thermal printer sold at sparkfun also has a different command set, but that one is different from standard EPSON too.


    Here is a list of supported ESC/POS commands:
    - ESC/POS command
    (HEX value)
    n value
    Print and Feed n dots paper ESC
    0x1b
    J
    \x4a
    n 1<=n<=255
    Set line space ESC
    0x1b
    1
    \31
    n 0<=n<=255
    Default: 0
    Set character space ESC
    \x1b
    p
    \x70
    n 0<=n<=255
    Default: 0
    Set right Margin ESC
    \x1b
    Q
    \x51
    n n: number of characters
    Default: 0
    Set left Margin ESC
    \x1b
    1
    \x6c
    n n: number of characters
    Default: 0
    Grey scale ESC
    \x1b
    m
    \x6d
    n 0<=n<=10
    Default: 5
    Set font Width ESC
    \x1b
    7
    \x37
    n 0,1,2,3,4
    Default: 0
    Set font Height ESC
    \x1b
    8
    \x38
    n 0,1,2,3,4
    Default: 0
    Underline ESC
    \x1b
    -
    \x2d
    n 0,1
    Default: 0
    Overline ESC
    \x1b
    +
    \x2b
    n 0,1
    Default: 0
    Inverse color ESC
    \x1b
    I
    \x69
    n 0,1
    Default: 0
    Reverse Direction ESC
    \x1b
    c
    \x63
    n 0,1
    Default: 1
    Initialize printer ESC
    \x1b
    @
    \x40
    Activate/Deactivate printer ESC
    \x1b
    d
    \x64
    n 0,1
    Default: 1
    Report printer status ESC
    \x1b
    v
    \x76
    n n=0 check paper
      return value:
      0x00 good
      0x04 no paper

    n=128 check printer
      return value:
      bit0: printing
      bit1: no paper
      bit4: overhead
      bit6: feeding paper
    Print and carriage return CR
    \x0d
    Line feed LF
    \x0a
    All the commands above are supported as advertised.

    Here are some examples:
    \x1b\x38\x02 double font height
    \x1b\x38\x00
    \x1b\x37\x02 double font width
    \x1b\x37\x00
    \x1b\x2b\x01 enable upperline
    \x1b\x2b\x00
    \x1b\x2d\x01 enable underline
    


    Bitmap Printing:  ESC K ml mh n1 n2...ni...

    The bitmap printing function is a bit tricky to use. As the printer does not come with any library, I need to code the drawing part.
    1. The bitmap prints as 1x8 pixel block concatenated as a 8px hight row.
    2. one row per command.
    3. ml & mh specifies how many data [i] is attached for the current row.  On x86 processors I need to take a hex value and reverse its higher/lower byte.
    4. The bitmap can not be printed along, must accompany some text before or after it. (CR or space is okay too) Other wise there is no output.

    The following example prints a 12 x 8 pixel image:


    Test print 
    \x1b\x4b\x30\x00\xff\xff\x00\x00\xff\xff\xff\x00\x00\xff\xff\xff\xff\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff
    
    # To make the image taller, just repeat the command N times.  Do not add {CR} or {LF} in between.
    
    Here is the printout:




    Mini-how-to: set baud-rate
    Hold down [set] button and power on the unit, it will print out a menu(in Chinese).  If you know how to read Chinese, the rest is easy.

    If you don't know how to read Chinese, here is the key sequence to config baud-rate:
    1) Press [LF] once to enter baud-rate setting sub-menu
    2) Press [set] to display available baud-rate. 2400 ~ 115200
    3) Press [LF] multiple times to select desired value.
    4) when desired baud-rate is printed, press [set] to confirm it.  Then it will print out the initial menu
    5) Press [set] once to save & exit.  Nothing should be printed out now.

    +1 to Stewart for bringing this question out.



    Final thoughts:

    The V6 printer is easy to work with, RS232 + TTL connection is a big plus if I need to attach it to different devices.

    It also comes with two cables. The printing quality is good compare to other lower priced printer on ebay (e.g. T5890). 

    Only problem is that it could be a challenge to implement QR-code and other barcode.  I wish the manufacturer would supply a bitmap printing library so this becomes much easier.