-
-
Notifications
You must be signed in to change notification settings - Fork 693
[ADD] pos_pywebdriver: support pywebdriver printing, even in Enterprise installs #1571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dreispt
wants to merge
1
commit into
OCA:19.0
Choose a base branch
from
ursais:19-dr-pos_pywebdriver
base: 19.0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| .. image:: https://odoo-community.org/readme-banner-image | ||
| :target: https://odoo-community.org/get-involved?utm_source=readme | ||
| :alt: Odoo Community Association | ||
|
|
||
| =========================== | ||
| POS PyWebDriver Integration | ||
| =========================== | ||
|
|
||
| .. | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| !! This file is generated by oca-gen-addon-readme !! | ||
| !! changes will be overwritten. !! | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| !! source digest: sha256:52ffe98ada0d1b8d9a5a25832cf759d3c861f2a9dc691bf2f6b22343ee06be71 | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
|
||
| .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
| :target: https://odoo-community.org/page/development-status | ||
| :alt: Beta | ||
| .. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png | ||
| :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html | ||
| :alt: License: LGPL-3 | ||
| .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpos-lightgray.png?logo=github | ||
| :target: https://github.com/OCA/pos/tree/19.0/pos_pywebdriver | ||
| :alt: OCA/pos | ||
| .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png | ||
| :target: https://translation.odoo-community.org/projects/pos-19-0/pos-19-0-pos_pywebdriver | ||
| :alt: Translate me on Weblate | ||
| .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png | ||
| :target: https://runboat.odoo-community.org/builds?repo=OCA/pos&target_branch=19.0 | ||
| :alt: Try me on Runboat | ||
|
|
||
| |badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
|
||
| This module enables Odoo 19 Point of Sale to print receipts via a | ||
| `PyWebDriver <https://github.com/pywebdriver/pywebdriver>`__ proxy, as | ||
| an alternative to the IoT Box. | ||
|
|
||
| PyWebDriver is an open-source Python service that exposes the same | ||
| ``/hw_proxy/`` HTTP endpoints as the Odoo IoT Box, allowing direct | ||
| ESC/POS printing without proprietary hardware. | ||
|
|
||
| Key features: | ||
|
|
||
| - Adds a **PyWebDriver** section to POS Settings, independent of the | ||
| IoT Box configuration. | ||
| - Mutually exclusive with IoT Box: enabling PyWebDriver mode disables | ||
| ``pos_iot``, and vice versa. | ||
| - Remaps the ``escpos`` driver key returned by PyWebDriver's | ||
| ``status_json`` to the ``printer`` key expected by Odoo 19, so the | ||
| connection status indicator works correctly. | ||
| - Uses Odoo's built-in ``HWPrinter`` (no custom printer logic needed). | ||
| - Works on Odoo Community and Enterprise Editions (the latter may | ||
| install the incompatible ``pos_iot`` module). | ||
|
|
||
| **Table of contents** | ||
|
|
||
| .. contents:: | ||
| :local: | ||
|
|
||
| Installation | ||
| ============ | ||
|
|
||
| PyWebDriver | ||
| ----------- | ||
|
|
||
| Install and start | ||
| `PyWebDriver <https://github.com/pywebdriver/pywebdriver>`__ on the | ||
| machine connected to the ESC/POS printer. Refer to the `PyWebDriver | ||
| documentation <https://github.com/pywebdriver/pywebdriver#readme>`__ for | ||
| installation and configuration instructions. | ||
|
|
||
| HTTPS requirement | ||
| ----------------- | ||
|
|
||
| In production (Odoo served over HTTPS), PyWebDriver must also run on | ||
| HTTPS to avoid mixed-content blocking by the browser. | ||
|
|
||
| The PyWebDriver Windows installer includes | ||
| ``generate_certificates.bat``, which: | ||
|
|
||
| 1. Installs the local CA into the OS/browser trust store | ||
| (``mkcert -install``) | ||
| 2. Generates locally-trusted certificates for ``localhost``, | ||
| ``127.0.0.1``, and ``::1`` | ||
|
|
||
| Run ``generate_certificates.bat`` once after installation. The generated | ||
| ``localhost+2.pem`` and ``localhost+2-key.pem`` are already referenced | ||
| in ``config\config.ini``. Set ``pywebdriver_ip`` in POS settings to | ||
| ``https://127.0.0.1:<port>``. | ||
|
|
||
| pos_iot | ||
| ------- | ||
|
|
||
| This module is **incompatible** with ``pos_iot``. If ``pos_iot`` is | ||
| installed, uninstall it before enabling PyWebDriver mode on any POS | ||
| configuration. | ||
|
|
||
| Configuration | ||
| ============= | ||
|
|
||
| 1. Go to **Point of Sale → Configuration → Settings** and select your | ||
| POS. | ||
| 2. Ensure **IoT Box** is **not** checked. | ||
| 3. Under the **PyWebDriver** section, enable **Enable PyWebDriver**. | ||
| 4. Set the **Proxy IP Address** to the URL where PyWebDriver is | ||
| listening (default: ``https://127.0.0.1:8069``). | ||
| 5. Save. | ||
|
|
||
| .. | ||
|
|
||
| **Note:** Enabling **IoT Box** will automatically disable | ||
| PyWebDriver, and enabling PyWebDriver will automatically disable IoT | ||
| Box. They cannot be active at the same time. | ||
|
|
||
| Usage | ||
| ===== | ||
|
|
||
| Once configured, open the POS session. The proxy connection is | ||
| established automatically on startup. | ||
|
|
||
| Status Indicator | ||
| ---------------- | ||
|
|
||
| The network status indicator in the POS navbar shows the proxy | ||
| connection state: | ||
|
|
||
| - **Green sitemap icon** — connected to PyWebDriver, printer ready. | ||
| - **Spinning icon** — connecting. | ||
| - **Red sitemap icon** — disconnected; check that PyWebDriver is | ||
| running and the IP address is correct. | ||
|
|
||
| Printing | ||
| -------- | ||
|
|
||
| Use the **Print Receipt** button as normal. Receipts are rendered as | ||
| JPEG images and sent to PyWebDriver via | ||
| ``/hw_proxy/default_printer_action``. | ||
|
|
||
| Troubleshooting | ||
| --------------- | ||
|
|
||
| +----------------------------------+----------------------------------+ | ||
| | Symptom | Likely cause | | ||
| +==================================+==================================+ | ||
| | Status indicator stays | PyWebDriver not running, or | | ||
| | disconnected | wrong IP/port in settings | | ||
| +----------------------------------+----------------------------------+ | ||
| | "Printing failed — unknown | PyWebDriver reachable but | | ||
| | error" | printer not responding; check | | ||
| | | ESC/POS connection | | ||
| +----------------------------------+----------------------------------+ | ||
| | Browser print dialog opens | ``use_pywebdriver`` not saved, | | ||
| | instead | or session cache stale — reload | | ||
| | | the POS page | | ||
| +----------------------------------+----------------------------------+ | ||
|
|
||
| Bug Tracker | ||
| =========== | ||
|
|
||
| Bugs are tracked on `GitHub Issues <https://github.com/OCA/pos/issues>`_. | ||
| In case of trouble, please check there if your issue has already been reported. | ||
| If you spotted it first, help us to smash it by providing a detailed and welcomed | ||
| `feedback <https://github.com/OCA/pos/issues/new?body=module:%20pos_pywebdriver%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
|
||
| Do not contact contributors directly about support or help with technical issues. | ||
|
|
||
| Credits | ||
| ======= | ||
|
|
||
| Authors | ||
| ------- | ||
|
|
||
| * Open Source Integrators | ||
|
|
||
| Contributors | ||
| ------------ | ||
|
|
||
| - Daniel Reis dreis@opensourceintegrators.com | ||
|
|
||
| Maintainers | ||
| ----------- | ||
|
|
||
| This module is maintained by the OCA. | ||
|
|
||
| .. image:: https://odoo-community.org/logo.png | ||
| :alt: Odoo Community Association | ||
| :target: https://odoo-community.org | ||
|
|
||
| OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
| mission is to support the collaborative development of Odoo features and | ||
| promote its widespread use. | ||
|
|
||
| This module is part of the `OCA/pos <https://github.com/OCA/pos/tree/19.0/pos_pywebdriver>`_ project on GitHub. | ||
|
|
||
| You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from . import models |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Copyright 2026 Open Source Integrators | ||
| # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). | ||
|
|
||
| { | ||
| "name": "POS PyWebDriver Integration", | ||
| "version": "19.0.1.0.0", | ||
| "category": "Point of Sale", | ||
| "summary": "Print POS receipts via PyWebDriver proxy instead of IoT Box", | ||
| "author": "Open Source Integrators, Odoo Community Association (OCA)", | ||
| "website": "https://github.com/OCA/pos", | ||
| "license": "LGPL-3", | ||
| "depends": ["point_of_sale"], | ||
| "excludes": ["pos_iot"], | ||
| "data": [ | ||
| "views/pos_config_views.xml", | ||
| ], | ||
| "assets": { | ||
| "point_of_sale._assets_pos": [ | ||
| "pos_pywebdriver/static/src/**/*.esm.js", | ||
| ], | ||
| }, | ||
| "installable": True, | ||
| "auto_install": False, | ||
| "application": False, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| from . import pos_config | ||
| from . import res_config_settings |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # Copyright 2026 Open Source Integrators | ||
| # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). | ||
|
|
||
| from odoo import api, fields, models | ||
| from odoo.exceptions import ValidationError | ||
|
|
||
|
|
||
| class PosConfig(models.Model): | ||
| _inherit = "pos.config" | ||
|
|
||
| use_pywebdriver = fields.Boolean( | ||
| string="Use PyWebDriver", | ||
| help="Connect receipt printer via a PyWebDriver proxy instead of IoT Box.", | ||
| default=False, | ||
| ) | ||
| pywebdriver_ip = fields.Char( | ||
| string="PyWebDriver IP Address", | ||
| help="URL of the PyWebDriver proxy, e.g. https://127.0.0.1:8069", | ||
| default="https://127.0.0.1:8069", | ||
| ) | ||
|
|
||
| @api.constrains("is_posbox", "use_pywebdriver") | ||
| def _check_pywebdriver_iot_exclusive(self): | ||
| for rec in self: | ||
| if rec.is_posbox and rec.use_pywebdriver: | ||
| raise ValidationError( | ||
| self.env._( | ||
| "IoT Box and PyWebDriver cannot both be enabled on " | ||
| "the same POS." | ||
| ) | ||
| ) | ||
|
|
||
| def write(self, vals): | ||
| # Auto-clear the other flag when one is enabled for better UX. | ||
| if vals.get("use_pywebdriver"): | ||
| vals.setdefault("is_posbox", False) | ||
| if vals.get("is_posbox"): | ||
| vals.setdefault("use_pywebdriver", False) | ||
| return super().write(vals) | ||
|
|
||
| @api.model | ||
| def _load_pos_data_read(self, records, config): | ||
| """When use_pywebdriver is enabled, shim the standard proxy fields so | ||
| the POS JS connects via PyWebDriver. is_posbox=True is required for the | ||
| useProxy getter.""" | ||
| read_records = super()._load_pos_data_read(records, config) | ||
| if read_records and config.use_pywebdriver and config.pywebdriver_ip: | ||
| record = read_records[0] | ||
| record["proxy_ip"] = config.pywebdriver_ip | ||
| record["is_posbox"] = True # required for useProxy getter | ||
| record["iface_print_via_proxy"] = True | ||
| return read_records | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Copyright 2026 Open Source Integrators | ||
| # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). | ||
|
|
||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class ResConfigSettings(models.TransientModel): | ||
| _inherit = "res.config.settings" | ||
|
|
||
| pos_use_pywebdriver = fields.Boolean( | ||
| related="pos_config_id.use_pywebdriver", | ||
| readonly=False, | ||
| ) | ||
| pos_pywebdriver_ip = fields.Char( | ||
| related="pos_config_id.pywebdriver_ip", | ||
| readonly=False, | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| [build-system] | ||
| requires = ["whool"] | ||
| build-backend = "whool.buildapi" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| 1. Go to **Point of Sale → Configuration → Settings** and select your | ||
| POS. | ||
| 2. Ensure **IoT Box** is **not** checked. | ||
| 3. Under the **PyWebDriver** section, enable **Enable PyWebDriver**. | ||
| 4. Set the **Proxy IP Address** to the URL where PyWebDriver is | ||
| listening (default: `https://127.0.0.1:8069`). | ||
| 5. Save. | ||
|
|
||
| > **Note:** Enabling **IoT Box** will automatically disable PyWebDriver, | ||
| > and enabling PyWebDriver will automatically disable IoT Box. They | ||
| > cannot be active at the same time. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| * Daniel Reis <dreis@opensourceintegrators.com> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| This module enables Odoo 19 Point of Sale to print receipts via a | ||
| [PyWebDriver](https://github.com/pywebdriver/pywebdriver) proxy, as an | ||
| alternative to the IoT Box. | ||
|
|
||
| PyWebDriver is an open-source Python service that exposes the same | ||
| `/hw_proxy/` HTTP endpoints as the Odoo IoT Box, allowing direct | ||
| ESC/POS printing without proprietary hardware. | ||
|
|
||
| Key features: | ||
|
|
||
| - Adds a **PyWebDriver** section to POS Settings, independent of the | ||
| IoT Box configuration. | ||
| - Mutually exclusive with IoT Box: enabling PyWebDriver mode disables | ||
| `pos_iot`, and vice versa. | ||
| - Remaps the `escpos` driver key returned by PyWebDriver's | ||
| `status_json` to the `printer` key expected by Odoo 19, so the | ||
| connection status indicator works correctly. | ||
| - Uses Odoo's built-in `HWPrinter` (no custom printer logic needed). | ||
| - Works on Odoo Community and Enterprise Editions | ||
| (the latter may install the incompatible `pos_iot` module). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| ## PyWebDriver | ||
|
|
||
| Install and start [PyWebDriver](https://github.com/pywebdriver/pywebdriver) | ||
| on the machine connected to the ESC/POS printer. Refer to the | ||
| [PyWebDriver documentation](https://github.com/pywebdriver/pywebdriver#readme) | ||
| for installation and configuration instructions. | ||
|
|
||
| ## HTTPS requirement | ||
|
|
||
| In production (Odoo served over HTTPS), PyWebDriver must also run on HTTPS to | ||
| avoid mixed-content blocking by the browser. | ||
|
|
||
| The PyWebDriver Windows installer includes `generate_certificates.bat`, which: | ||
|
|
||
| 1. Installs the local CA into the OS/browser trust store (`mkcert -install`) | ||
| 2. Generates locally-trusted certificates for `localhost`, `127.0.0.1`, and `::1` | ||
|
|
||
| Run `generate_certificates.bat` once after installation. The generated | ||
| `localhost+2.pem` and `localhost+2-key.pem` are already referenced in | ||
| `config\config.ini`. Set `pywebdriver_ip` in POS settings to | ||
| `https://127.0.0.1:<port>`. | ||
|
|
||
| ## pos_iot | ||
|
|
||
| This module is **incompatible** with `pos_iot`. If `pos_iot` is | ||
| installed, uninstall it before enabling PyWebDriver mode on any POS | ||
| configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| Once configured, open the POS session. The proxy connection is | ||
| established automatically on startup. | ||
|
|
||
| ## Status Indicator | ||
|
|
||
| The network status indicator in the POS navbar shows the proxy | ||
| connection state: | ||
|
|
||
| - **Green sitemap icon** — connected to PyWebDriver, printer ready. | ||
| - **Spinning icon** — connecting. | ||
| - **Red sitemap icon** — disconnected; check that PyWebDriver is running | ||
| and the IP address is correct. | ||
|
|
||
| ## Printing | ||
|
|
||
| Use the **Print Receipt** button as normal. Receipts are rendered as | ||
| JPEG images and sent to PyWebDriver via `/hw_proxy/default_printer_action`. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| | Symptom | Likely cause | | ||
| |---|---| | ||
| | Status indicator stays disconnected | PyWebDriver not running, or wrong IP/port in settings | | ||
| | "Printing failed — unknown error" | PyWebDriver reachable but printer not responding; check ESC/POS connection | | ||
| | Browser print dialog opens instead | `use_pywebdriver` not saved, or session cache stale — reload the POS page | |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry. I dont understand why not use native field. Proxy_ip
https://github.com/odoo/odoo/blob/19.0/addons/point_of_sale/models/pos_config.py#L125