2

In CUPS, I want to hold all new printer jobs, check the cartridge levels of my printer and one by one release jobs for printing. (My printer kills the cartridge-chips when falling below a certain percentage to prevent refilling.)

I have CUPS notifications working (RSS) and can get my cartridge levels. Now, I want to enable the 'hold-new-jobs' attribute on a specific printer in CUPS (.../printers/myPrinter). After this, I have to find out how to get all jobs that are on-hold and release one (by job ID, or so) (preferably FIFO(FHFR)) For completeness: If cartridges are below a threshold, the jobs are held until cartridges are reset (manually) and a button in Home Assistant is pressed.

Pycups (libcups Python bindings) seems undocumented and different enough from libcups itself to get lost. There seems to be no example of IPPRequests for pycups. This is my shot at it (to_pdf as testprinter):

import cups

# Response is a set of bytes. Not clear (to me) what it means and if its parsed or can be parsed somewhere.
def ipp_hold_new_jobs_request_handler(response):
    print("Hold_all_jobs handler called. Response: {}".format(response))


ipp_request = cups.IPPRequest(cups.IPP_OP_HOLD_NEW_JOBS)
ipp_attribute = cups.IPPAttribute(cups.IPP_TAG_OPERATION, cups.IPP_TAG_URI, "printer-uri",
                                  "http://cups.mydomain.ext:631/printers/to_pdf")
ipp_request.add(ipp_attribute)
response = ipp_request.writeIO(ipp_hold_new_jobs_request_handler)
print('repsonse: {}'.format(response)) # Returns -1

while True:
    pass

I expect new jobs to be shown as on-hold in the CUPS web-interface if this request succeeds.

Maybe I am doing this entirely the wrong way. I hope that someone can help me get this right. Thanks.

1 Answers1

1

I think that it is not possible to use the pycups API like this. The correct way to send an IPP request is through the cupsDoRequest API call, but that part of the API currently is not directly exposed by pycups.

The writeIO method works on a much lower level and is typically used internally by the CUPS code to actually serialize a request. The callback, that it expects is supposed to write the serialized data to the HTTP connection, so your ipp_hold_new_jobs_request_handler function would need to do that, but it cannot because it does not have access to the underlying HTTP connection.

The closest thing to what happens when calling cupsDoRequest that could actually be done in this function would be calling the writeRequestData method of a Connection object, but this will not work either because before calling writeRequestData, the appropriate HTTP headers must be sent (that is part of what is done by cupsDoRequest) and pycups does not expose the APIs that are needed to do that.

In summary, pycups does currently not allow to send arbitrary IPP requests. Only the methods provided by the Connection class can be used to send requests.