Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions src/escpos/escpos.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
:copyright: Copyright (c) 2012-2017 Bashlinux and python-escpos
:license: MIT
"""

from __future__ import annotations

import logging
import re
import textwrap
import time
Expand Down Expand Up @@ -94,6 +96,7 @@
ImageWidthError,
SetVariableError,
TabPosError,
ValidationError,
)
from .magicencode import MagicEncode

Expand Down Expand Up @@ -1421,26 +1424,55 @@ def panel_buttons(self, enable: bool = True) -> None:
else:
self._raw(PANEL_BUTTON_OFF)

def query_status(self, mode: bytes) -> bytes:
def query_status(self, mode: bytes, raise_not_valid=False) -> bytes:
"""Query the printer for its status.

Returns byte array containing it.

:param mode: Integer that sets the status mode queried to the printer.
- RT_STATUS_ONLINE: Printer status.
- RT_STATUS_PAPER: Paper sensor.
:param raise_not_valid: Default False.
False to log error but do not raise exception.
:raises: :py:exc:`~escpos.exceptions.ValidationError`
"""
self._raw(mode)
status = self._read()
is_valid = self._check_valid_response(status)
if not is_valid:
logging.error("Invalid status data: Could't get a valid printer response.")
if raise_not_valid:
raise ValidationError(
"An attemp to read a response value from the device returned an invalid response"
)
return b""
return status

def _check_valid_response(self, resp: bytes) -> bool:
"""Check a byte to be a valid ESC/POS response.

Check if a byte is in the format 0xx1xx10 which is the unique way to
distinguish a possible printer's response from other bytes.

A printer response is obtained after a Real Time Status Query command (DLE EOT).

:param resp: A byte containing the printer's response.
"""
if len(resp) == 0 or len(resp) > 1:
return False
# Check bits 7 or 0 are not 1
is_valid_7_0 = (resp[0] & 0b10000001) == 0b00000000
# Return True if additionally bits 4 and 1 are 1
return is_valid_7_0 and (resp[0] & 0b00010010) == 0b00010010

def is_online(self) -> bool:
"""Query the online status of the printer.

:returns: When online, returns ``True``; ``False`` otherwise.
"""
status = self.query_status(RT_STATUS_ONLINE)
if len(status) == 0:
logging.warning("Unknown online status data")
return False
return not (status[0] & RT_MASK_ONLINE)

Expand All @@ -1454,7 +1486,8 @@ def paper_status(self) -> int: # could be IntEnum
"""
status = self.query_status(RT_STATUS_PAPER)
if len(status) == 0:
return 2
logging.warning("Unknown paper status data")
return 0
if status[0] & RT_MASK_NOPAPER == RT_MASK_NOPAPER:
return 0
if status[0] & RT_MASK_LOWPAPER == RT_MASK_LOWPAPER:
Expand Down
25 changes: 25 additions & 0 deletions src/escpos/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- `90` = Device not found :py:exc:`~escpos.exceptions.DeviceNotFoundError`
- `91` = USB device not found :py:exc:`~escpos.exceptions.USBNotFoundError`
- `100` = Set variable out of range :py:exc:`~escpos.exceptions.SetVariableError`
- `110` = Invalid response format :py:exc:`~escpos.exceptions.ValidationError`
- `200` = Configuration not found :py:exc:`~escpos.exceptions.ConfigNotFoundError`
- `210` = Configuration syntax error :py:exc:`~escpos.exceptions.ConfigSyntaxError`
- `220` = Configuration section not found :py:exc:`~escpos.exceptions.ConfigSectionMissingError`
Expand Down Expand Up @@ -344,6 +345,30 @@ def __str__(self) -> str:
return f"Set variable out of range ({self.msg})"


class ValidationError(Error):
"""Invalid response format.

An error occurred while validating data.
The return code for this exception is `110`.

inheritance:

.. inheritance-diagram:: escpos.exceptions.ValidationError
:parts: 1

"""

def __init__(self, msg: str = "") -> None:
"""Initialize ValidationError object."""
Error.__init__(self, msg)
self.msg = msg
self.resultcode = 110

def __str__(self) -> str:
"""Return string representation of ValidationError."""
return f"Invalid data ({self.msg})"


# Configuration errors


Expand Down