Device scripts are segments of code that run when either a user logs in to a device, a print job is released at the device, or a copy, scan, or fax job has been completed. The script is defined using the concept of a “hook”. A hook is a JavaScript function that is defined by you, the script writer. It is also commonly referred to as an entry point or method.
A number of device hooks (entry points) are available and each differ by the point in the workflow when they are called. For example, a hook early in the workflow has the ability to influence behavior later in the flow, while scripts late will correspondingly have access to additional information that would not be available earlier.
Script hooks (entry points)
The available device hooks are:
Device workflow hooks
Hook | Description |
---|---|
deviceLoginHook(inputs, actions) | Use this hook for either:
Point of Call: Immediately after a user has entered their login credentials/PIN/card swipe for authentication. Limitations: Cannot analyze any jobs (copy/scan/fax/ held print jobs) at this point. Use cases for this hook Generally, use this hook for any "Session" actions such as:
|
deviceJobLogHook(inputs, actions) | Use this hook to analyze and process a copy/fax/scan job after the job has been completed. Think of it as a post job processing hook that allows you to change the job's properties (ie change the cost, add a comment). Point of Call: Once the device has sent through a list of job logs for processing. Limitations: This hook can't be used to block device function jobs (as the job has already finished). Use cases:
|
devicePrintReleaseHook(inputs, actions) | Use this hook to analyze and block release of held print jobs at the device. Point of Call: Immediately after the user tries to release held print job(s) at the device. Limitations:
Use case: Prevent the release of jobs charged to a particular account at some devices. For example, a University could prevent the release of jobs charged to the Arts department from any printer outside the Arts building. |
All hooks have access to user, device, and utilities information. In addition, each hook has access to specific information, such as device job information for deviceJobLogHook
. The scripts have access to these through the two function arguments:
-
inputs
- access to the job, user, and device information.inputs
are read-only and any modification to variables do not affect the job. -
actions
- Access to perform actions that can influence the job processing, e.g. tochange the job cost. All actions (also known as side-effects) must be performed via the availableactions
.
All available inputs
and actions
are listed below.
Script Inputs
User Info (inputs.user)
User Info Script Reference (inputs.user)
Property/Method | Description |
---|---|
inputs.user.username | (string) The username of the user that has logged into the device. |
inputs.user.fullName | (string) The full name of the user who has logged into the device. |
inputs.user.email | (string) The email address of the user that has logged into the device. |
inputs.user.office | (string) The office of the user that has logged into the device. |
inputs.user.department | (string) The department of the user that has logged into the device. |
inputs.user.restricted | (boolean) Determines if the user is restricted. |
inputs.user.balance | (number) The user's current account balance. |
inputs.user.getBalance(accountName) | (number) The user's current account balance. When a user has multiple personal accounts, the user's current account balance. Parameters:
|
inputs.user.isInGroup(groupName) | Determines if the user belongs to the given group name (as defined on the Groups tab). Parameters:
|
inputs.user.getProperty(propName) | Return a value as a Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
inputs.user.getNumberProperty(propName) | A convenience method to return a value as a Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
inputs.user.defaultSharedAccountName | (string) Gets the default shared account name for a user (if configured). If not configured, returns an empty string (""). |
inputs.user.autoChargeToSharedAccountName | (string) If the user has an autocharge to shared account, returns the name of that shared account. If there is no autocharge to shared account, returns an empty string (""). |
inputs.user.canChargeToPersonalAccount | (boolean) Determines if the user can charge to their personal account. Device and printer overrides supersede this setting. |
inputs.user.canOnlyChargeToPersonalAccount | (boolean) Determines if the user can charge only to their personal account (ie if the Account Selection setting in the Admin web interface is:
Device and printer overrides supersede this setting. |
inputs.user.canSelectSharedAccount | (boolean) Determines if the user has permission to select a shared account. |
inputs.user.canSelectAccountFromList | (boolean) Determines if the user can select a shared account from a list. Device and printer overrides supersede this setting. |
inputs.user.canSelectAccountUsingPin | (boolean) Determines if the user can select a shared account using PIN codes. Device and printer overrides supersede this setting. |
inputs.user.isInternal | (boolean) Determines if the user is an internal user. |
inputs.user.primaryCardNumber | (string) Returns the primary card number if configured. If not configured, returns an empty string (""). |
inputs.user.secondaryCardNumber | (string) Returns the secondary card number if configured. If not configured, returns an empty string (""). |
inputs.user.cardPin | (string) Returns the card PIN for a user if configured. If not configured, returns an empty string (""). |
Device Info (inputs.device)
Device Info Script Reference (inputs.device)
Property/Method | Description |
---|---|
inputs.device.serverName | (string) The name of the server where the device is hosted. |
inputs.device.deviceName | (string) The name of the device. |
inputs.device.fullDeviceName | (string) The full name of the device in the format |
inputs.device.isDisabled | (boolean) Determines if this device is currently disabled. |
inputs.device.groups | (Array) An array of all the device groups that this device is a member of. |
inputs.device.isInGroup(groupName) | (boolean) Determines if the device belongs to a particular device group. Parameters:
|
inputs.device.getProperty(propName) | Return a value as a Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
inputs.device.getNumberProperty(propName) | A convenience method to return a value as a Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
Utilities (inputs.utils)
Utilities Script Reference (inputs.utils)
Method | Description |
---|---|
inputs.utils.formatBalance(amount) | Formats the balance amount based on the server currency settings. Returns a string. Parameters:
|
inputs.utils.formatCost(amount) | Formats the cost amount (e.g. a job cost) based on the server currency settings. Returns a string. Parameters:
|
inputs.utils.formatNumber(amount, decimals) | Formats a number with the given number of decimal places. Returns a string. Parameters:
|
inputs.utils.getProperty(propName) | Return a value as a Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
inputs.utils.getNumberProperty(propName) | A convenience method to return a value as a Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
Device Job Info (inputs.job)
Device Job Info Script Reference (inputs.job)
Property/Method | Description |
---|---|
inputs.job.copies | (number) The number of copies. The |
inputs.job.date | (date) The date/time of the copy, scan, or fax job. |
inputs.job.paperSizeName | (string) The paper size name (e.g. Letter, Tabloid, A4, A3). |
inputs.job.isGrayscale | (boolean) Determines if the copy, scan, or fax job is grayscale (i.e. contains no color). |
inputs.job.isColor | (boolean) Determines if the copy, scan, or fax job is color (i.e. contains at least one color page). |
inputs.job.isDuplex | (boolean) Determines if the copy, scan, or fax job is duplex. |
inputs.job.totalGrayscalePages | (number) The total number of grayscale pages in the copy, scan, or fax job. |
inputs.job.totalColorPages | (number) The total number of color pages in the copy, scan, or fax job. |
inputs.job.totalPages | (number) The total number of pages in the copy, scan, or fax job. |
inputs.job.totalSheets | (number) The total number of sheets of paper produced by the copy, scan, or fax job. |
inputs.job.selectedSharedAccountName | (string) The full name of the selected shared account. If no shared account is selected then an empty string is returned (""). |
inputs.job.username | (string) The username of the user that performed the copy, scan, or fax job. |
inputs.job.isSimplex | (boolean) Determines if the copy, scan, or fax job is simplex. |
inputs.job.isFax | (boolean) Determines if it's a fax job. |
inputs.job.isScan | (boolean) Determines if it's a scan job. |
inputs.job.isCopy | (boolean) Determines if it's a copy job. |
inputs.job.duplexPages | (number) The number of duplex pages. |
inputs.job.isInvoiced | (boolean) Determines if the copy, scan, or fax job is invoiced. |
inputs.job.cost | (number) The cost of the job. The cost returned is the cost of the job after all other cost adjustments have been applied. |
inputs.job.calculateCostForDevice(deviceName) | (number) Calculates the cost of this job on another device. This can be used in combination with This returns the cost of the job. Parameters:
|
inputs.job.comment | (string) The comment for the copy, scan, or fax job. |
inputs.job.documentName | (string) The document name. |
Held job Info (inputs.heldJob)
Held Job Info Script Reference (inputs.heldJob
)
Property/Method | Description |
---|---|
inputs.heldJob.documentName | (string) Name of the document. |
inputs.heldJob.clientMachineOrIP | (string) The machine name or IP address of the client workstation where the job was printed. If both the machine name and the IP address are known, the machine name is returned. |
inputs.heldJob.isColor | (boolean) Determines if the job is color (i.e. contains at least one color page). |
inputs.heldJob.isDuplex | (boolean) Determines if the job is duplex. |
inputs.heldJob.isGrayscale | (boolean) Determines if the job is grayscale (i.e. contains no color). |
inputs.heldJob.cost | (number) The cost of the job. |
inputs.heldJob.totalPages | (number) The total number of pages in the print job. |
inputs.heldJob.printerName | (string) The printer name. |
inputs.heldJob.date | (date) The date/time the job was printed. |
inputs.heldJob.fullPrinterName | (string) The full name of the printer including the server name, in the format server\printer. |
inputs.heldJob.username | (string) The username of the user that printed the job. |
inputs.heldJob.selectedSharedAccountName | (string) The full name of the selected shared account. If no shared account is selected then an empty string is returned (""). |
inputs.heldJob.isSimplex | (boolean) Determines if the job is simplex. |
inputs.heldJob.copies | (number) The number of copies. |
inputs.heldJob.printerServerName | (string) The name of the server the print queue is hosted on. |
inputs.heldJob.isChargeToPersonalAccount | (boolean)Determines if the job is being charged to personal account. |
inputs.heldJob.isChargeToSharedAccount | (boolean) Determines if the job is being charged to a shared account. |
inputs.heldJob.isInvoice | (boolean)Determines if the job is being invoiced. |
inputs.heldJob.comment | (string) Returns the comment. If there is no comment, an empty string is returned (""). |
inputs.heldJob.paperSizeName | (string) The paper size name (e.g. Letter, Tabloid, A4, A3). |
Script Actions
User actions (actions.user)
User Actions Script Reference (actions.user)
Method | Description |
---|---|
actions.user.onCompletionSaveProperty(propName, value[, options]) | Creates a custom-defined persistent user property with a specific value. This operation is performed when the hook has finished running. Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
actions.user.onCompletionIncrementNumberProperty(propName, value[, options]) | A convenience method that increments the value of a custom-defined persistent user property. This operation is performed when the hook has finished running. Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
Device actions (actions.device)
Device Actions Script Reference (actions.device)
Method | Description |
---|---|
actions.device.onCompletionSaveProperty(propName, value[, options]) | Creates a custom-defined persistent device property with a specific value. This operation is performed when the hook has finished running. Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
actions.device.onCompletionIncrementNumberProperty(propName, value[, options]) | A convenience method that increments the value of a custom-defined persistent user property. This operation is performed when the hook has finished running. Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
Utility actions (actions.utils)
Utility Actions Script Reference (actions.utils)
Method | Description |
---|---|
actions.utils.sendEmail(recipient, subject, body) | Sends an email to an email address or username. Parameters:
|
actions.utils.sendEmail(recipients, subject, body) | Sends an email to one or many email addresses or usernames. Parameters:
Example: to send an email to many email addresses or usernames |
actions.utils.onCompletionSaveProperty(propName, value[, options]) | Saves a global value as a Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
actions.utils.onCompletionIncrementNumberProperty(propName, value[, options]) | A convenience method to increment a global number value associated with a persistent custom-defined property. This operation is performed once the hook has finished running. Parameters:
For more information about using storage properties, see Custom-defined persistent properties (storage). |
Log Actions (actions.log)
Log Actions Script Reference (actions.log)
Method | Description |
---|---|
actions.log.info(message) | Logs an informational message to the Application Log. Parameters:
|
actions.log.warning(message) | Logs an warning message to the Application Log. Parameters:
|
actions.log.error(message) | Logs an error message to the Application Log. Parameters:
|
actions.log.debug(message) | Logs a message to the server's text-based log file ( Parameters:
|
Login Actions (actions.login)
Login Actions Script Reference (actions.log)
Method | Description |
---|---|
actions.login.denyLoginAccess() | Block the user from logging in to the device. Note: This action takes priority over the |
actions.login.bypassLoginFilters() | Allows a user to bypass any configured login filters and restrictions and access a device. Note: This action will not work if the action |
actions.login.denyCopyAccess() | Block both color and grayscale copying on login. This feature is not supported for all device types so make sure you test before using in a live environment. |
actions.login.denyColorCopyAccess() | Block color copying on login. This feature is not supported for all device types so make sure you test before using in a live environment. Note: This action takes priority over |
actions.login.bypassColorCopyFilters() | Allows a user to bypass any configured color copying filters and restrictions and grants them color copying access. Note: This action will not work if |
actions.login.setAvailableSharedAccounts(parentNames) | Restrict the shared accounts available at the device by creating a whitelist of approved accounts. A user who logs into the device can charge only to their shared accounts if those accounts have been whitelisted. Parameters:
Note: This action takes effect on the “Account Selection” screen. Please review recipe “Restrict selectable shared accounts on device” to address corner cases. This action accepts only parent shared accounts. Any child accounts will be implicitly included in the whitelist when the parent account is listed. Example: To allow for only Science related shared accounts to be selected on the device:
In the above example, a user who belongs to two faculties and can charge to both “Biology” and “Arts” shared accounts, but will only be able to charge to “Biology” when accessing this device (as “Arts” has not been whitelisted). |
Job actions (actions.job)
Job Actions Script Reference (actions.job)
Method | Description |
---|---|
actions.job.setCost (cost) | Sets the cost of the job. Note: If there are other cost adjustments configured (e.g. user cost overrides), these will be applied before the Parameters:
|
actions.job.addComment (comment) | Appends a comment to the job. This is logged to the database and is available in the job logs and reports. If the job already has a comment (e.g. set by the user with the advanced client) then this appends to the existing comment. Parameters:
|
Held Print Job actions (actions.heldJob)
Held Print Job Actions Script Reference (actions.job)
Method | Description |
---|---|
actions.heldJob.blockRelease(message) | Block the user from releasing a held print job and display a customizable message on the device screen to notify the user as to why the job was blocked from release. If the user releases multiple held print jobs at the same time, then calling this action on at least one of those held print jobs will subsequently block the other jobs from being released. Parameters:
|
actions.heldJob.blockRelease() | Block the user from releasing a held print job. A default message will be displayed on the device screen to notify the user that the held print job was denied due to print restrictions. If the user releases multiple held print jobs at the same time, then calling this action on at least one of those held print jobs will subsequently block the other jobs from being released. |
Custom-defined persistent properties (storage)
Device scripts have the ability to store or save information between executions. They allow you to implement advanced logic that takes advantage of not just the current job event information, but any information that has been stored by previous script events. Properties can also be used to share data between different scripts. Some ideas that can be implemented with device script properties include:
-
Rate limits – knowledge of previous jobs in the given period need to be stored/known.
-
Detecting duplicate events/situations over time.
-
Detecting repeatable user behavior. e.g. how many times a user uses duplex in a row.
-
Shared settings between scripts . e.g. Global defined configuration variables/settings.
Properties are key-value pair storage that are associated with a user or device, or optionally can be global. Keys are Strings that uniquely define the property. Values are stored as strings and are any data that can be converted to and from a string. The maximum length of a key is 70 characters, and the value is 1,000 characters.
Working with properties
Properties are fetched via the getProperty
call on the associated source. For example, to fetch a property stored for:
-
the user associated with the login or job (depending on the hook), use
inputs.user.getProperty("my-key")
-
the device, use
inputs.device.getProperty()
, -
global properties, use
inputs.utils.getProperty()
.
There is also a set of convenience methods called getNumberProperty()
if dealing exclusively with a number.
By default, properties are saved (to the database) only after the hook is completed.
You can also set the values of properties. For example, to set a property on the user, use:
actions.user.onCompletionSaveProperty("my-key", "my-value")
Implementing Counters (Advanced)
There are two ways to implement a counter (e.g. a page number count). One approach is to get the current value, increment, then save. However, on high volume networks, another event might overwriting the value. Device scripts provide a convenient method that avoids this called onCompletionIncrementNumberProperty()
. See the recipe “Impose a daily color copy limit” for an example.
Device script requirements (advanced)
These notes are intended for advanced developers “pushing the limits” of device script functionality. All device scripts must conform to the following technical requirements:
-
Timeouts: All scripts’ execution logic should complete within 5 seconds of CPU time. Failure to comply (for example, due to an infinite loop), results in the script terminating and raising a runtime error. Five seconds is adequate as even the most advanced example recipes complete within a few milliseconds.
-
Idempotent: All scripts should remain idempotent. It’s expected to provide the same output given the same input. Side-effects based off logic other than the
inputs
are not recommended. For example, logic based off the result ofMath.random()
would violate this principle.
Comments