feat: printer beep support for kitchen tickets
Adds configurable buzzer control so the printer alerts kitchen staff
on each new ticket print.
Backend:
- printer_service.py: ESC 0x07 beep command fired before paper cut,
reads print.beep_on_ticket / print.beep_pattern settings; supports
single/double/triple/long presets and a custom:n1:n2:n3 format
- settings.py: registers the two new print.beep_* settings with
defaults (beep_on_ticket=true, beep_pattern=double)
- system.py: POST /api/system/printers/test-beep endpoint for
live testing from the dashboard
Frontend (PrintFontsTab):
- BeepSection component with preset grid, custom n1/n2/n3 inputs,
and a live test-beep button targeting any configured printer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,8 @@ _PRINT_SETTING_KEYS = [
|
||||
"print.font_ingredient",
|
||||
"print.font_item_note",
|
||||
"print.font_order_note",
|
||||
"print.beep_on_ticket",
|
||||
"print.beep_pattern",
|
||||
]
|
||||
|
||||
_PRINT_SETTING_DEFAULTS = {
|
||||
@@ -80,6 +82,17 @@ _PRINT_SETTING_DEFAULTS = {
|
||||
"print.font_ingredient": "0:0:0",
|
||||
"print.font_item_note": "0:0:0",
|
||||
"print.font_order_note": "0:1:0",
|
||||
"print.beep_on_ticket": "true",
|
||||
"print.beep_pattern": "double",
|
||||
}
|
||||
|
||||
# Beep patterns: (n1=on×100ms, n2=off×100ms, n3=count)
|
||||
# Using ESC BEL n1 n2 n3 (0x1B 0x07 n1 n2 n3)
|
||||
_BEEP_PATTERNS = {
|
||||
"single": (2, 2, 1), # one 200ms beep
|
||||
"double": (1, 1, 2), # two short beeps
|
||||
"triple": (1, 1, 3), # three short beeps
|
||||
"long": (5, 2, 1), # one 500ms beep
|
||||
}
|
||||
|
||||
# SIZE byte values (ESC ! base, no bold bit):
|
||||
@@ -179,6 +192,21 @@ def is_spoof_mode() -> bool:
|
||||
db.close()
|
||||
|
||||
|
||||
def send_test_beep(ip: str, port: int, n1: int, n2: int, n3: int) -> Tuple[bool, str]:
|
||||
"""Send a standalone beep-only job. n1=on-time×100ms, n2=off-time×100ms, n3=count."""
|
||||
if is_spoof_mode():
|
||||
logger.info("Spoof printing ON — dropping test beep")
|
||||
return True, ""
|
||||
try:
|
||||
p = _get_printer(ip, port)
|
||||
p._raw(bytes([0x1b, 0x07, n1, n2, n3]))
|
||||
p.close()
|
||||
return True, ""
|
||||
except Exception as e:
|
||||
logger.error("Test beep failed for %s:%s — %s", ip, port, e)
|
||||
return False, str(e)
|
||||
|
||||
|
||||
def send_test_print(ip: str, port: int, name: str) -> Tuple[bool, str]:
|
||||
if is_spoof_mode():
|
||||
logger.info("Spoof printing ON — dropping test print for %s", name)
|
||||
@@ -563,6 +591,22 @@ def _print_kitchen_ticket(p: Network, order: Order, items: List[OrderItem], db:
|
||||
p._raw(b'\x1b\x21\x00')
|
||||
|
||||
p._raw(b'\n\n\n')
|
||||
|
||||
# Beep before cut so the buzzer fires as the paper advances
|
||||
beep_enabled = cfg.get("print.beep_on_ticket", "true") == "true"
|
||||
if beep_enabled:
|
||||
pattern = cfg.get("print.beep_pattern", "double")
|
||||
if pattern.startswith("custom:"):
|
||||
# custom:n1:n2:n3
|
||||
try:
|
||||
_, n1s, n2s, n3s = pattern.split(":")
|
||||
beep_bytes = (int(n1s), int(n2s), int(n3s))
|
||||
except (ValueError, TypeError):
|
||||
beep_bytes = _BEEP_PATTERNS["double"]
|
||||
else:
|
||||
beep_bytes = _BEEP_PATTERNS.get(pattern, _BEEP_PATTERNS["double"])
|
||||
p._raw(bytes([0x1b, 0x07, beep_bytes[0], beep_bytes[1], beep_bytes[2]]))
|
||||
|
||||
p.cut()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user