2020/03/30

Laser printer vs UPS

As an extra wrinkle to the previous post, the new Lexmark is on an UPS. Yes, I can hear you screaming "NEVER PUT A LASER PRINTER ON AN UPS" but I'm a professional, I know what I'm doing. Specifically, I over-engineered my solution.

The problem with a laser printer on a UPS is you might be tempted to print something during a black out. And your UPSes battery will never supply the current your fuser needs. My solution is to build a plug with relays connected to an arduino connected to a computer connected to the UPS. When power goes out, apcupsd on the computer runs a small script that sends a command to the arduino via USB to turn off the relays. The arduino also has a momentary switch. When I push the switch, the arduino turns the relays on. I also have small script that sends the command to turn the relays on.

I probably could have avoided the arduino and used a transistor latch. Power off turns the latch and relays off. Only a button press turns the latch and relays on. But then I couldn't do the following.

One annoying """feature""" of the Lexmark is that it has AirPrint and Wi-fi. I have yet to find out how to turn these off. So the printer spends most of its time turned off. So I wrote a CUPS backend that checks if the printer is on, sends the arduino the "turn on" command if it isn't, then chains to the normal socket backend to actually send the data to the printer.

#!/bin/bash

HWEL=10.0.0.68
LOG=/tmp/hwel-driver.log

if [[ $# == 1 ]] ; then
    exec /usr/lib/cups/backend/socket "$@"
fi

function aping () {
    local host=$1
    if ping -c 1 -q $host >/dev/null ; then
        return 0
    fi
    return 1
}

function ping_wait () {
    local host=$1
    while true ; do
        if ping -c 1 -q $host >/dev/null ; then
            return
        fi
        sleep 2
    done
}


status=$(/sbin/apcaccess status localhost:3552 | grep STATUS | cut -d: -f 2)
if [[ $status =~ ONLINE ]] ; then
    echo "INFO: hwel battery status=$status" | tee -a $LOG >&2
else
    echo "ERROR: hwel battery status=$status" | tee -a $LOG >&2
    exit 17
fi

aping $HWEL || sudo /home/fil/bin/hwel-on
ping_wait $HWEL

export DEVICE_URI=socket://$HWEL:9100
exec /usr/lib/cups/backend/socket "$@"

I put this script in /usr/lib/cups/backend/hwel and tell CUPS to use a new URL.

lpadmin -p hwelraw -v hwel://hwel.localdomain:9100

Yes, my printer is called Hwel. Yes, I name all my printers after Discworld dwarfs.

Windows 10 vs Lexmark

So I have a new Lexmark MB2236adw laser printer. For some reason beyond my ken, Windows 10 keeps saying it's offline, when clearly it isn't. Printer works fine from Linux, so I decided that Windows is going to print via CUPS.

First, create a raw printer on your CUPS host:

lpadmin -p hwelraw -v socket://hwel.localdomain:9100 -E \
     -D "Lexmark on UPS (raw)" -L "Philip's Office" -o raw

Then add the following to cups.conf to allow printing via the network:

<Location /printers>
    Order allow,deny
    Allow localhost
    Allow 10.0.0.*
</Location>

Remember to restart CUPS

service cups reload

Open up the port 631 in iptables.

Now on the windows computer, install the Lexmark drivers.

Then you have to turn on IPP : Control Panel > Programs > Turn Windows Features On or Off > Print and Document Services > Internet Printing Client must be checked.

Now it's time to Add a printer, using the The printer that I want isn’t listed button. You are going to be using an http URL, that will look like http://scott/pritners/hwelraw. Replace scott with your Linux computer's name and hwelraw with the CUPS queue name. Select the printer driver installed previously, print your test page and bask in the glory of getting a computer to do your bidding.

As a bonus step, print a 2 page document to make sure Windows can print double sided because my new printer does cool things like that.