pklaus / brother_ql

Python package for the raster language protocol of the Brother QL series label printers (QL-500, QL-550, QL-560, QL-570, QL-700, QL-710W, QL-720NW, QL-800, QL-810W, QL-820NWB, QL-1050, QL-1060N and more).
GNU General Public License v3.0
547 stars 156 forks source link

Feature Request: Printer Status #76

Open Danielwsx64 opened 4 years ago

Danielwsx64 commented 4 years ago

I don't know if it is possible but I have a need to see if the printer is ok to print. Some times its starts blinking the red led because of some error and I would like to know before send other print.

bobbysmith007 commented 4 years ago

If this info / status could additionally provide the currently loaded label roll that would be amazing

raddessi commented 4 years ago

I need this as well, if there is anything I can assist with on the development side please let me know, I'll be digging for more information on how it works on my own for now until I can get something mocked up.

arbu commented 4 years ago

I implemented a module, that can read the status of the printer here: https://github.com/arbu/printui/blob/master/printui/printer.py. Maybe it could be integrated into this repo. So far I was only able to test this with a QL-570. But I included all fields I could find in the documentation files on the brother website. (If you want to test this: the PrinterDevice class in that file currently does not work well with the brother_ql convert() function. The convert() functions adds a status information request in the middle of the print command which is not handled. To prevent that remove the call to qlr.add_status_information() in brother_ql/conversion.py.)

debuglevel commented 3 years ago

Reading the current label type would be great, as it could be used to eliminate possible errors! :-)

arnotixe commented 3 years ago

@arbu I can confirm the printui module works well with QL-800 too.

arnotixe commented 3 years ago

Is there a way to raise a bounty to implement this in the command line tool, @pklaus ? some $ to a paypal account maybe? :smiley: I'd be happy to chip in!

SkoZombie commented 4 months ago

Here is code that will get you printer status using only brother_ql, based brother_ql.backends.helpers.send(). It will give you a dict() containing:

Along with the raw bytes if you need them for some reason.

@pklaus should be able to just dump this function in the helpers.py if he's interested.

import logging
import time
from typing import Optional

from brother_ql.backends import backend_factory, guess_backend
from brother_ql.reader import interpret_response

logger = logging.getLogger(__name__)

# Status request is standard ESC/P status response
# See page 18 of https://download.brother.com/welcome/docp000678/cv_qlseries_eng_raster_600.pdf
STATUS_MSG = b'\x1b\x69\x53'

def status(printer_identifier: Optional[str] = None, backend_identifier: Optional[str] = None, timeout: int = 10) \
        -> dict | None:
    """
    Request status instruction from a printer. Based on ``brother_ql.backends.helpers.send()``

    :param str printer_identifier: Identifier for the printer.
    :param str backend_identifier: Can enforce the use of a specific backend.
    :param int timeout: How long to wait for the printer read. Status response should be pretty quick so the default of
                        10 is overkill but kept to align with ``send()``
    :return: None if the status command failed, or dict() containing information populated by ``interpret_response()``
             if it was successful
    """

    selected_backend = backend_identifier
    if not backend_identifier:
        try:
            selected_backend = guess_backend(printer_identifier)
        except ValueError:
            logger.info("No backend stated. Selecting the default linux_kernel backend.")
            selected_backend = 'linux_kernel'

    be = backend_factory(selected_backend)
    BrotherQLBackend = be['backend_class']      # noqa

    printer = BrotherQLBackend(printer_identifier)

    start = time.time()
    logger.info('Sending instructions to the printer. Total: %d bytes.', len(STATUS_MSG))
    printer.write(STATUS_MSG)

    while time.time() - start < timeout:
        data = printer.read()
        if not data:
            time.sleep(0.005)
            continue
        try:
            result = interpret_response(data)
            result['raw_bytes'] = data
        except ValueError:
            logger.error("TIME %.3f - Couldn't understand response: %s", time.time() - start, data)
            continue
        return result

    return None