testsAndMisc/python_pkg/brother_printer/constants.py
Krzysztof kuhy Rudnicki c985160d17 WIP: Enforce 500-line limit - split batch 1
Split 16+ files. 27 files still need splitting. See session notes.
2026-03-16 22:46:48 +01:00

174 lines
5.2 KiB
Python

"""Constants, status codes, and lookup tables for Brother printer checking."""
from __future__ import annotations
import sys
# ── Colors ───────────────────────────────────────────────────────────
RED = "\033[0;31m"
YELLOW = "\033[1;33m"
GREEN = "\033[0;32m"
CYAN = "\033[0;36m"
BOLD = "\033[1m"
DIM = "\033[2m"
RESET = "\033[0m"
# ── SNMP supply level sentinel values ────────────────────────────────────────
SNMP_LEVEL_OK = -3
SNMP_LEVEL_LOW = -2
SUPPLY_LOW_PCT = 10
SUPPLY_WARN_PCT = 25
PROGRESS_BAR_WIDTH = 25
# Brother HL-1110 consumable page ratings
TONER_RATED_PAGES = 1000
DRUM_RATED_PAGES = 10000
CUPS_PAGE_LOG_PATH = "/var/log/cups/page_log"
CONSUMABLE_STATE_DIR = ".config/brother_printer"
MIN_LPSTAT_JOB_PARTS = 4
BROTHER_USB_VENDOR_ID = 0x04F9
def _out(text: str = "") -> None:
"""Write a line to stdout."""
sys.stdout.write(text + "\n")
def _prompt(text: str) -> str:
"""Read user input with a prompt."""
sys.stdout.write(text)
sys.stdout.flush()
return sys.stdin.readline().strip()
# ── Brother PJL status codes ────────────────────────────────────────
# Documented in Brother PJL Technical Reference.
# Format: code -> (severity, short_text, action)
# Severities: ok, info, warn, critical
BROTHER_STATUS_CODES: dict[int, tuple[str, str, str]] = {
10001: ("ok", "Ready", ""),
10002: ("ok", "Sleep", ""),
10003: ("info", "Self-test / Calibrating", ""),
10004: ("ok", "Warming up", ""),
10005: ("ok", "Cooling down", ""),
10006: ("info", "Processing", ""),
10007: ("info", "Printing", ""),
10014: ("ok", "Cancelling", ""),
10023: ("info", "Waiting", ""),
# Toner
30010: (
"warn",
"Toner Low",
"Order replacement toner cartridge (TN-1050/TN-1030 compatible).",
),
30038: (
"warn",
"Toner Low",
"Order replacement toner cartridge (TN-1050/TN-1030 compatible).",
),
40038: (
"warn",
"Toner Low",
"Order replacement toner cartridge (TN-1050/TN-1030 compatible).",
),
40309: (
"critical",
"Replace Toner",
"The toner cartridge needs immediate replacement"
" (TN-1050/TN-1030 compatible).",
),
40310: (
"critical",
"Toner End",
"The toner cartridge is empty." " Replace now (TN-1050/TN-1030 compatible).",
),
# Drum
30201: (
"warn",
"Drum End Soon",
"The drum unit is nearing end of life."
" Order replacement (DR-1050 compatible).",
),
40201: (
"warn",
"Drum End Soon",
"The drum unit is nearing end of life."
" Order replacement (DR-1050 compatible).",
),
40019: (
"critical",
"Replace Drum",
"The drum unit must be replaced (DR-1050 compatible).",
),
40020: (
"critical",
"Drum Stop",
"The drum unit must be replaced immediately (DR-1050 compatible).",
),
# Paper / feed
40000: ("critical", "Paper Jam", "Clear the paper jam and close all covers."),
40300: (
"critical",
"No Paper / Tray Open",
"Load paper or close the paper tray.",
),
40302: ("critical", "No Paper", "Load paper into the paper tray."),
40016: ("warn", "Paper Feed Error", "Check paper tray and re-seat paper."),
# Cover
41000: ("critical", "Cover Open", "Close the top cover of the printer."),
41001: ("critical", "Cover Open", "Close the front cover of the printer."),
# Others
35078: ("info", "Manual Feed", "Load paper in the manual feed slot."),
42000: (
"critical",
"Machine Error",
"Power-cycle the printer. If error persists, contact service.",
),
}
# ── CUPS status code mappings ────────────────────────────────────────
_CUPS_REASONS_TO_STATUS: dict[str, int] = {
"paused": 10023,
"moving-to-paused": 10023,
"toner-low": 30010,
"toner-empty": 40310,
"marker-supply-low": 30010,
"marker-supply-empty": 40310,
"media-empty": 40302,
"media-needed": 40302,
"media-jam": 40000,
"cover-open": 41000,
"door-open": 41000,
"input-tray-missing": 40300,
}
_CUPS_STATE_TO_STATUS: dict[str, int] = {
"idle": 10001,
"processing": 10007,
"stopped": 10023,
}
_ERROR_REASON_MAP: tuple[tuple[tuple[str, ...], str, str], ...] = (
(("media-jam",), "40000", "Paper Jam"),
(("cover-open", "door-open"), "41000", "Cover Open"),
(("toner-empty",), "40310", "Toner End"),
(("toner-low",), "30010", "Toner Low"),
)
def get_status_info(code: str) -> tuple[str, str, str]:
"""Look up a PJL status code. Returns (severity, text, action)."""
try:
return BROTHER_STATUS_CODES[int(code)]
except (KeyError, ValueError):
return (
"info",
f"Unknown status (code {code})",
"Check printer display for details.",
)