17 October 2014

Kinokero (cloudprint) tutorial part 1

Kinokero Tutorial Part 1: Getting Started

Using Google Cloudprint Proxy Connector in Ruby

Kinokero is a ruby gem which provides a complete Google CloudPrint Proxy Connector functionality. That means that it can turn any OS-connected printer into a cloudprint accessible printer, as long as the internet connection is maintained.

The gem itself includes separate classes to handle the GCP server protocol (Cloudprint), the GCP Jingle notification protocol (Jingle), and a class for interacting with CUPS devices on a linux system (Printer). Persistence is expected to be handled by whatever is invoking Kinokero. The initial beta release of kinokero is working for CUPS-style printer on linux-like OSs.

Parts 1 and 2 of this tutorial will show how to get kinokero up and running in a ruby application, focusing only on the highest Proxy-level, and will not show how to interact directly with the lower-level Google Cloudprint Services (GCPS), such as takes place in the Class Cloudprint.

The kinokero gem itself has a small working code to invoke the gem. It is contained in the console folder and represents the best template for getting the gem working. This tutorial will cover the preparation (Part 1) and the key points of invoking the gem (Part 2).

Note: I use Ruby 2.0 in an RVM environment on an Ubuntu (linux) workstation, so this tutorial will be specific to that type of environment. You will also want to make sure you have registered, with CUPS, a working printer on your *nix system.

Registering with Google APIs; setting environment variables

You'll need a client ID for your proxy for obtaining OAuth2 authorization codes, as the GCP documentation points out:
The client ID can be obtained as explained  here ». [relevant portion shown below] Client IDs don't need to be unique per printer: in fact, we expect one client ID per printer manufacturer.

Before your application can use Google's OAuth 2.0 authentication system for user login, you must set up a project in the Google Developers Console to obtain OAuth 2.0 credentials, set a redirect URI, and (optionally) customize the branding information that your users see on the user-consent screen. You can also use the Developers Console to create a service account, enable billing, set up filtering, and do other tasks. For more details, see the Google Developers Console Help.
Specifically, you'll end up with four items that you'll need to put into the environmental variables accessible by your application. This is done as environmental variables for security concerns, so that the values won't appear in any public repositories for either the gem or your application. See below for names and sample data. I put these into my .bashrc file. This only needs to be done once for no matter how many proxy connectors you wish to invoke.

  export GCP_PROXY_API_PROJECT_NBR=407407407407
  export GCP_PROXY_API_CLIENT_EMAIL="407407407407@developer.gserviceaccount.com"
  export GCP_PROXY_CLIENT_ID="407407407407-abcd1abcd2abcd3abcd4abcd5abcd5ef.apps.googleusercontent.com"
  export GCP_PROXY_CLIENT_SECRET="someSECRETencryptedValue"

The CLIENT_SECRET will be a typical encrypted gibberish.

On a personal note, using the Google Developers Console to get these values was not straightforward. So you may have trial & error wrong turns as you go about trying to coax these values out of the Great And Wonderful Wizard of Oz.

Adding a resource for persistence

The Kinokero proxy requires the invoking code to provide persistence for GCPS-issued information (such OAUTH2 tokens, printer id, etc). One of the reasons for this is when (or unexpectedly if) the entire machine running the proxy is restarted, the cloudprint printers, which had already been registered, need to be brought on-line with GCPS. This is accomplished through persistence of the critical information.

The console itself relies on a yaml file for persistence ( console/config/gcp_seed.yml ).

Kinokero has a primary hash which is required by several of the classes within the gem. In the README, this is called 'gcp_control' hash, and is discussed in detail in that document. The yaml seed file is used to prep this hash prior to instantiating a Proxy object.

Adding seed data for a test printer

To set up the seed data for your test printer, go to your OS and discover the name of an attached printer.
  $ lpstat -v

device for laserjet_1102w: hp:/net/HP_LaserJet_Professional_P_1102w?ip=
device for lp_null: ///dev/null

In the sample shown above, there are two printers registered: "laserjet_1102w" and "lp_null." The former is the only working actual printer, so this would be chosen to be the test printer. We'll next need to discovery the full path to the PPD file for that printer. On an Ubuntu system, it will be: /etc/cups/ppd/laserjet_1102w.ppd . You will need to convert this into the gcp v2.0 required CDD format. Google has a handy converter that makes that easy. You can access it here ». Once you've converted the file, name it and place it in: /etc/cups/cdd/laserjet_1102w.cdd .

You'll also need information about the actual device: manufacturer, model, firmware version number, serial number for the printer (aka uuid), and some URLs for setup, support, and updates for the printer. I'm not sure how GCPS uses these, if at all, at this time.

Armed with this information, edit console/config/gcp_seed.yml, obviously replacing with your actual values in the appropriate places. The following attributes are required prior to registering the test printer.
  item: 'test',
  cups_alias: 'laserjet_1102w',
  gcp_printer_name: 'gcp_test_printer',
  capability_ppd: '/etc/cups/ppd/laserjet_1102w.ppd',
  capability_cdd: '/etc/cups/cdd/laserjet_1102w.cdd',
  gcp_uuid: 'VND3R11877',
  gcp_manufacturer: 'Hewlett-Packard',
  gcp_model: 'LaserJet P1102w',
  gcp_setup_url: 'http://www8.hp.com/us/en/campaigns/wireless-printing-center/printer-setup-help.html',
  gcp_support_url: 'http://h10025.www1.hp.com/ewfrf/wc/product?product=4110396&lc=en&cc=us&dlc=en&lang=en&cc=us',
  gcp_update_url: 'http://h10025.www1.hp.com/ewfrf/wc/product?product=4110396&lc=en&cc=us&dlc=en&lang=en&cc=us',
  gcp_firmware: '20130703'

In Part 2, we'll show how to instantiate a kinokero proxy object and register a printer.