{"id":30699694,"url":"https://github.com/ircama/pyprintlpr","last_synced_at":"2026-01-20T17:34:41.295Z","repository":{"id":304601775,"uuid":"1018939499","full_name":"Ircama/PyPrintLpr","owner":"Ircama","description":"LPR (RFC 1179) printer client/server with proxy support","archived":false,"fork":false,"pushed_at":"2025-08-09T09:21:42.000Z","size":46,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-21T16:19:36.970Z","etag":null,"topics":["epson","esc-pos","lpr","rfc-1179"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ircama.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-13T11:43:47.000Z","updated_at":"2025-08-09T10:44:19.000Z","dependencies_parsed_at":"2025-07-14T07:41:34.576Z","dependency_job_id":"0869608d-ae0a-4a82-8bec-1a7f20fd9b1c","html_url":"https://github.com/Ircama/PyPrintLpr","commit_stats":null,"previous_names":["ircama/pylpr","ircama/pyprintlpr"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/Ircama/PyPrintLpr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ircama%2FPyPrintLpr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ircama%2FPyPrintLpr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ircama%2FPyPrintLpr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ircama%2FPyPrintLpr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ircama","download_url":"https://codeload.github.com/Ircama/PyPrintLpr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ircama%2FPyPrintLpr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273273342,"owners_count":25076147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["epson","esc-pos","lpr","rfc-1179"],"created_at":"2025-09-02T11:12:34.916Z","updated_at":"2025-10-29T01:41:46.165Z","avatar_url":"https://github.com/Ircama.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LPR printer client/server with proxy support\n\nRFC 1179 client and server toolkits and Python library for interacting with printers via LPR protocol or RAW mode, as well as a proxy/server for debugging, job capture, and protocol analysis.\n\n## Features\n\n- RFC 1179 LPR protocol implementation\n- Easy-to-use Python API for client and server LPR features\n- LPR (515) and RAW (9100) protocol support\n- Print job simulation and debugging\n- Bidirectional TCP/UDP proxy and traffic inspection\n- Job queue management and archiving\n- Hexdump tracing and protocol analysis\n- Advanced Epson ESC/P2 (if epson_escp2 is installed)\n- Cross-platform (Windows, Linux, macOS)\n\n## Installation\n\n```bash\npip install PyPrintLpr\npip install epson_escp2  # Support advanced debugging of the Epson ESC/P2 protocol with the \"server -d\" option\n```\n\n## Command Line Usage\n\n```\nUsage: python -m pyprintlpr [client|server] [args...]\n  client: Run the print client\n  server: Run the proxy/server\n  args: use --help to get the client and server usage.\n```\n\n### Client\nRun the client to send print jobs to a printer:\n\n```\nusage: pyprintlpr client [-h] -a ADDRESS [-p PORT]\n                         (-P | -s LIST | -S LIST | -R LIST | -f PRINT_FILE) [-d]\n                         [-e] [-q QUEUE] [-r] [-t TIMEOUT] [-b RECV_BUFFER]\n                         [-u USERNAME] [-l LABEL] [-j JOB_NAME]\n\nRAW and LPR print client.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -a ADDRESS, --address ADDRESS\n                        Printer host name or IP address. (Example: -a 192.168.1.87)\n  -p PORT, --port PORT  Printer port (default is \"LPR\" = 515)\n  -P, --print           Send the \"Print any waiting jobs\" command (RFC1179 0x01) to\n                        the specified queue and exit.\n  -s LIST, --status LIST\n                        Send queue state (short) command with \"list\" attribute\n                        (RFC1179 0x03) to the specified queue and print the result.\n  -S LIST, --longstatus LIST\n                        Send queue state (long) command with \"list\" attribute\n                        (RFC1179 0x04) to the specified queue and print the result.\n  -R LIST, --remove LIST\n                        Remove jobs command with \"list\" attribute (RFC1179 0x05) to\n                        the specified queue.\n  -f PRINT_FILE, --file PRINT_FILE\n                        File to be printed\n  -d, --debug           Print debug information\n  -e, --epson           Use Epson header and footer\n  -q QUEUE, --queue QUEUE\n                        Queue name; default queue name is \"PASSTHRU\"\n  -r, --reserved        Use reserved port range 721-731 (RFC 1179 requirement)\n  -t TIMEOUT, --timeout TIMEOUT\n                        Timeout (default: 5.0 seconds)\n  -b RECV_BUFFER, --buffer RECV_BUFFER\n                        Receive buffer size (default: 4096 bytes)\n  -u USERNAME, --username USERNAME\n                        User name (default: current user)\n  -l LABEL, --label LABEL\n                        Label for the job (optional, used to set the name of source\n                        file)\n  -j JOB_NAME, --job JOB_NAME\n                        Job name (default: \"LprClientJob\")\n\nRAW/LPR print client.\n```\n\nNotes:\n\n- Use the `epson` flag to send Epson-specific headers/footers\n- Use the `reserved` flag to comply with RFC 1179 reserved port requirements\n- Debugging: Enable logging for protocol analysis\n\n### Server/Proxy\n\nRun the server/proxy to capture, forward, or analyze print jobs:\n\n```\nusage: pyprintlpr server [-h] [-a ADDRESS] [-t] [-d] [-I] [-i] [-s] [-p SAVE_PATH] [-q] [-l PORTS] [-e PORTS]\n                         [--timeout TIMEOUT]\n\nRAW and LPR print server with proxy, forward and local loopback features.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -a ADDRESS, --address ADDRESS\n                        Printer IP address (if not provided, runs in local-only mode)\n  -t, --trace           Enable hex dump tracing\n  -d, --decode          Decode data file including Epson sequences (requires epson_escp2)\n  -I, --show-image      When decoding, also show image (requires epson_escp2)\n  -i, --dump-image      When decoding, also dump image (requires epson_escp2)\n  -s, --save-files      Save received print jobs to disk\n  -p SAVE_PATH, --save-path SAVE_PATH\n                        Path name of the directory including the saved jobs (defaut: \"lpr_jobs\")\n  -q, --quiet           Do not print debug data\n  -l PORTS, --loopback PORTS\n                        Comma-separated list of ports to loopback instead of forwarding to the target IP (e.g.,\n                        \"515,9100\")\n  -e PORTS, --exclude PORTS\n                        Comma-separated list of ports to exclude from tracing (e.g., \"515,9100\")\n  --timeout TIMEOUT     Timeout in seconds for receiving control/data files (default: 10.0 seconds)\n\nRAW/LPR print server.\n```\n\n## Python API Usage\n\n### Client API\nThe client API allows sending print jobs, check queue status, and interact with printers programmatically.\n\n#### Basic Usage\n\n```python\nfrom pyprintlpr import LprClient\n\nwith LprClient('192.168.1.100', port=\"LPR\", queue='PASSTHRU') as printer:\n    # Send a print job from a file\n    with open('document.txt', 'rb') as f:\n        printer.send(f.read())\n```\n\n#### LprClient Class Reference\n- `LprClient(hostname, port=515, queue='PASSTHRU', ...)` – Initialize client\n\n    - **hostname** (`str`):  \n      Printer hostname or IP address to connect to.\n\n    - **port** (`int` or `str`, default: `9100`):  \n      Port number for the printer. Use `9100` or `RAW` for RAW printing, `515` or `\"LPR\"` for LPR protocol.\n\n    - **timeout** (`float`, default: `5.0`):  \n      Socket timeout in seconds for network operations.\n\n    - **queue** (`str`, default: `\"PASSTHRU\"`):  \n      LPR queue name, used when sending jobs via LPR protocol.\n\n    - **recv_buffer** (`int`, default: `4096`):  \n      Size of the receive buffer for socket operations.\n\n    - **username** (`str`, optional):  \n      Username for LPR jobs. Defaults to the current system user if not specified.\n\n    - **job_name** (`str`, optional):  \n      Job name for LPR jobs. Defaults to `\"LprClientJob\"` if not specified.\n\n    - **file_name** (`str`, optional):  \n      File name for LPR jobs. Defaults to the job name if not specified.\n\n    - **use_reserved_port** (`bool`, default: `False`):  \n      If `True`, attempts to use a reserved source port (721-731) as required by RFC 1179 for LPR protocol.\n\n- Methods:\n\n    | **Method**              | **Description**                                                                                                                  |\n    | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------- |\n    | `connect()`             | Opens a TCP socket connection to the printer at the specified host and port, with timeout.                                       |\n    | `disconnect()`          | Gracefully shuts down and closes the socket connection if open.                                                                  |\n    | `send(data: bytes)`     | Sends `bytes` directly to the printer over the socket connection.                                                            |\n    | `remote_cmd(cmd: str, args: bytes)` | Constructs a Remote Mode command: 2-byte ASCII command + 2-byte little-endian length + arguments.                                |\n    | `set_timer`             | Constructs the \"TI\" remote command to synchronize RTC by setting the current time.                                               |\n\n- Context manager support: `with LprClient(...) as printer:`\n\n#### Epson Remote Mode commands\n\n`LprClient` can be used to send *Epson Remote Mode commands* to the printer. Notice that the LPR or RAW channels do not support receiving payload responses from the Epson printer.\n\nComprehensive, unified documentation for Epson’s *Remote Mode commands* does not exist: support varies by model, and command references are scattered across service manuals, programming guides and third-party sources (for example, the [Developer's Guide to Gutenprint](https://gimp-print.sourceforge.io/reference-html/x952.html) or [GIMP-Print - ESC/P2 Remote Mode Commands](http://osr507doc.xinuos.com/en/OSAdminG/OSAdminG_gimp/manual-html/gimpprint_37.html)).\n\nGeneral sequences:\n\n| **Command**           | **Description**                                              | **String**   |\n| --------------------- | ------------------------------------------------------------ |------------- |\n| `LF`                  | Line Feed (new line).                                        |              |\n| `SP`                  | Space.                                                       |              |\n| `NUL`                 | b'\\x00'.                                                     |              |\n| `FF`                  | Form Feed (b'\\x0c'); flushes the buffer / ejects the page.   |              |\n| `INITIALIZE_PRINTER`  | Resets printer to default state (ESC @).                     |              |\n\nSpecific Epson sequences:\n\n| **Command**           | **Description**                                              | **String**   |\n| --------------------- | ------------------------------------------------------------ |------------- |\n| `EXIT_PACKET_MODE`    | Exit IEEE 1284.4 (D4) packet mode. See [1], 5.1.1 Exit Packet Mode. Must be sent before any other command. |              |\n| `REMOTE_MODE`         | Enter Epson Remote Command mode. See [1], 6.1.1 Enter Remote Mode  | `(R`         |\n| `ENTER_REMOTE_MODE`   | Initialize printer and enter Epson Remote Command mode.      |              |\n| `EXIT_REMOTE_MODE`    | Exits Remote Mode. See [1], 6.1.14 Terminate Remote Mode |              |\n| `JOB_START`           | Begins a print job. \"JS\", b'\\x00\\x00\\x00\\x00'. See [1], Start job “JS” nn 00H 00H \u003cjob name\u003e m1. It is necessary to send the TI command before the JS command. | `JS`         |\n| `JOB_END`             | Ends a print job. \"JE\", b'\\x00'. See [1], End job “JE” 01H 00H 00H | `JE`         |\n| `PRINT_NOZZLE_CHECK`  | Triggers a nozzle check print pattern. \"NC\", b'\\x00\\x00'     | `NC`         |\n| (nozzle check)        | \"NC\", b'\\x00\\x10'                                            | `NC`         |\n| `VERSION_INFORMATION` | Requests firmware or printer version info. \"VI\", b'\\x00\\x00' | `VI`         |\n| `LD`                  | Load NVR Settings. See [1], Load Power-On Default NVR into RAM (Remote Mode) \"LD\" 00H 00H | `LD`         |\n| (Run print-head cleaning) | \"CH\" 02H 00H 00H                                         | `CH`         |\n| (Return the printer ID) | ESC 01 @EJL [sp] ID\\r\\n | `ID` |\n\n[1]: handbook named \"EPSON Programming Guide For 4 Color EPSON Ink Jet Printer XP-410 (Level I)\", also including the description of following remote mode commands:\n\nDescription    | Command | Syntax\n-------------- | -- | ----------------------------------\nSet printer timer, synchronize RTC | TI | \"TI\" 08H 00H 00H YYYY MM DD hh mm ss\nSet horizontal print position | FP | “FP” 03H 00H 00H m1 m2\nTurn printer state reply on/off | ST | “ST” 02H 00H 00H m1\nSet Job Name | JH | Job name set “JH” nL nH 00H m1 m2 m3 m4 m5 \u003cjob name\u003e\nPaper Feed Setup | SN | Set mechanism sequence \"SN\" 01H 00H 00H\nSet Media information | MI | Select paper media “MI” 04H 00H 00H m1 m2 m3\nSet double paper print | DP | Select Duplex Printing “DP” 02H 00H 00H m1\nSet user setting | US | User Setting “US” 03H 00H 00H m1 m2\nSelect paper path | PP | Select paper path “PP” 03H 00H 00H m1 m2\nSave Setting | SV | “SV” 00H 00H\n\nSee https://gimp-print.sourceforge.io/reference-html/x952.html for other ones.\n\nThe following code prints the nozzle-check print pattern:\n\n```python\nfrom pyprintlpr import LprClient\n\nwith LprClient('192.168.1.100', port=\"LPR\", queue='PASSTHRU') as lpr:\n    data = (\n        lpr.EXIT_PACKET_MODE +    # Exit packet mode\n        lpr.ENTER_REMOTE_MODE +   # Engage remote mode commands\n        lpr.PRINT_NOZZLE_CHECK +  # Issue nozzle-check print pattern\n        lpr.EXIT_REMOTE_MODE +    # Disengage remote control\n        lpr.JOB_END               # Mark maintenance job complete\n    )\n    lpr.send(data)\n```\n\nSome usage examples:\n\n```cmd\npython3 -m pyprintlpr client -a 127.0.0.1 -f SECURITY.md -p lpr  # Send SECURITY.md to the LPR server using the default queue\npython3 -m pyprintlpr client -a 127.0.0.1 -p lpr -s user -q PASSTHRU  # List queue (compact form)\npython3 -m pyprintlpr client -a 127.0.0.1 -p lpr -S user -q PASSTHRU  # List queue (long form)\npython3 -m pyprintlpr client -a 127.0.0.1 -p lpr -P  # Traverse all jobs to be printed by the default queue\npython3 -m pyprintlpr client -a 127.0.0.1 -p lpr -R job  # Remove a job\n```\n\n### Server/Proxy API\nCapture, forward, manage LPR requests. Also process RAW requests.\n\n#### Basic Usage\n```python\nfrom pyprintlpr import LprServer\n\nserver = LprServer(save_files=True, save_path='lpr_jobs')\n# The server can be integrated into an asyncio event loop for advanced use\n# For simple usage, run via command line or module interface\n```\n\n#### LprServer Class Reference\n- `LprServer(save_files=True, save_path=None)` – Initialize server\n\n  - `save_files` (`bool`, default: `True`):\n    If `True`, received print jobs (control and data files) are saved to disk. If `False`, jobs are discarded after dumping data.\n  - `save_path` (`str`, default: `\"lpr_jobs\"`):\n    if `save_files` is set to `True`, directory path where received print jobs are saved. If not specified, defaults to \"lpr_jobs\" in the current working directory.\n\n- `get_next_job_id()` – Generate next job ID\n- `parse_control_file(content: bytes)` – Parse LPR control file\n- `format_queue_status(queue: str, long_format=False)` – Format queue status\n- `save_job_files(job: LPRJob)` – Save job files to disk\n\n## Examples\n\n### Run the server:\n\nTo open the port 161 with Linux O.S., the server shall be run as root.\n\n```bash\npython3 -m pyprintlpr server -a 192.168.1.100 -t -l 515\n\npython3 -m pyprintlpr server -a 192.168.178.29 -e 3289,161 -d -s -l 515,9100  # decode the Epson ESC/P2 protocol.\n```\n\n### Send print job:\n```python\nfrom pyprintlpr import LprClient\n\nwith LprClient('192.168.1.100', port=9100) as printer:\n    printer.send(b'\\x1B@Hello Printer!\\x0C')\n```\n\n### Run as a module\n```bash\npython -m pyprintlpr client -a 192.168.1.100 -f file.txt\npython -m pyprintlpr server -a 192.168.1.100 -t\n```\n\n## License\n\nEUPL-1.2 License - See [LICENSE](LICENSE.txt) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fircama%2Fpyprintlpr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fircama%2Fpyprintlpr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fircama%2Fpyprintlpr/lists"}