cputil Server Integration
The cputil
tool is intended to be as easy as possible to integrate with any server side web development technology. For this to be possible, a small number of requirements need to be met:
- The server side scripting language must allow you to invoke external processes and obtain their output.
- The web host allows running native binaries from your server side scripts.
- The host server environment must be of a type supported by .NET Core. At this time, that includes Windows (32 and 64bit), Linux (64 bit and Arm - including Raspberry Pi), and Mac OS 64bit.
Invoking cputil
PHP
PHP has several methods of triggering an external process and reading the output by command, or including the output directly in an HTTP response. Please refer to the system()
, passthru()
and exec()
functions.
In most situations, passthru()
can be used to directly insert cputil output into your response. for example, calling cputil mediatypes-mime text/vnd.star.markup
will output JSON data that be included as the value for the mediaTypes
field of a CloudPRNT POST response, when printing is needed (in this example, to print a star markup document).
Note
We should add some example code here if possible.
Python
Note
Talk with David Pearce, or do some research to create some advice or samples here.
Lua
Note
Do some research to create some advice or samples here.
Node.js
In a Node.js environment, cputil can be invoked as an external process by using the native child_process
module. For convenience, the child_process module provides a handful of synchronous and asynchronous alternatives. Please refer to the child_process.exec()
, child_process.execSync()
, child_process.execFile()
, child_process.execFileSync()
functions. For certain use cases, such as automating shell scripts, the synchronous counterparts may be more convenient. However, be mindful that synchronous methods can have an impact on performance due to stalling the event loop while spawned processes complete.
For example, to start cputil as a child process and convert ASB status into JSON:
const child_process = require('child_process');
var jsonStatus = child_process.execFileSync('cputil', ['jsonstatus', req.body.status]);
console.log(JSON.parse(jsonStatus));
When to use cputil on the server
cputil is intended to assist with CloudPRNT specific requirements of developing a server. As such, the pain uses are expected to be when handling the CloudPRNT POST and GET requests. The primary function of cputil is to convert print jobs from one format to another. This is useful for CloudPRNT servers, because not all devices will support the same output commands of print data formats. Instead, CloudPRNT provides a mechanism through which a server and client can negotiate a job data format that both support. To avoid adding work and complexity to the server-side code (in particular, the need to convert or render print jobs in multiple ways), cputil can help with the negotiation, and automatically convert print jobs as needed.
POST Requests (CloudPRNT Poll)
CloudPRNT client devices will issue regular HTTP POST requests to the specified URL on your server. These POST requests are used to inform your server of the current device state, and allow your server to respond with requests. POST requests are triggered at a regular, specified interval, or if a client-side event occurs, such as the printer status changing, a barcode being scanned etc. Servers can use the POST response to request that the client prints a job, update a line display, request additional information about the client (for example paper size/print area), set a custom ID for the device and other similar requests.
Developers can use cputil at this point to aid in two areas:
- Decoding Status - the POST request will include both a simple device status code, and more detailed Star ASB format status information. Using the status code alone is enough in many situations, but if a server needs to know more detail, then it needs to decode the bitmasked information from hexadecimal data included in the ASB status string. This is not convenient to do in many server side scripting languages, and so cputil can be used to convert the Star ASB string into formatted JSON. Please refer to the Decoding Star ASB Status section of the usage page for details.
- Managing print job formats - When requesting a print job, cputil can be used to generate the correct value of the
mediaTypes
field of the JSON response.
Managing print job formats
When using cputil, servers can prepare a print job using their preferred method without worrying about which formats the client device can support. Currently this can be as PNG, JPEG, BMP, GIF, ASCII/UTF8 text or using Star Document Markup.
When a server receives a POST request, and it needs to print a job, then it should provide a JSON format response with the fields jobReady
set to true
and mediaTypes
set to a list of strings which describe media types that can be provided to the client.
For example, a bash shell script called through cgi to generate a suitable response could be:
#!/bin/bash
# Make a CloudPRNT post response to print a Star Markup job with cputil
OUTPUT_TYPES=`cputil mediatypes-mime text/vnd.star.markup`
echo "{"
echo " \"jobReady\": true,"
echo " \"mediaTypes\": $OUTPUT_TYPES"
echo "}"
would produce the JSON output:
{
"jobReady": true,
"mediaTypes": ["text/vnd.star.markup","application/vnd.star.line","application/vnd.star.starprnt","application/vnd.star.starprntcore"]
}
GET Requests (fetching the job)
CloudPRNT devices will perform an HTTP GET request to your server when they have been asked to print a job. The device will have selected a compatible data format from the mediaTypes list, and this will be provided as a query string parameter to the GET. Servers can use cputil in their GET handler to convert the job from the servers internally used data format, to the CloudPRNT devices requested format.
For example, the following bash script, if called as a CGI script to handle a GET request, will convert a local Star Document Markup file into the format requested by the printer.
#!/bin/bash
urldecode() {
local data=${1//+/ }
printf '%b' "${data//%/\x}"
}
# parse query string
declare -A param
while IFS='=' read -r -d '&' key value; do
param["$key"]=$value
done <<<"${QUERY_STRING:+"${QUERY_STRING}&"}"
# get the output format requested by the cloudprnt device
OUTPUT_FORMAT=`urldecode "${param["type"]}"`
# get the unique ID of the CloudPRNT device which requested the print job
CP_MAC=`urldecode "${param["mac"]}"`
# Assume that print jobs are stored in a local file and named according the the device MAC address ID
INPUT_FILE="printjob-$CP_MAC.stm"
# use cputil to convert the input file and write directly to standard output
cputil decode "$OUTPUT_FORMAT" "$INPUT_FILE" -