{"id":51372792,"url":"https://github.com/hightower-systems/station-hardware-agent","last_synced_at":"2026-07-03T08:34:26.394Z","repository":{"id":365824815,"uuid":"1273937122","full_name":"hightower-systems/station-hardware-agent","owner":"hightower-systems","description":"Local HTTP agent bridging a browser or cloud web app to USB station hardware: ESC/POS receipt printer + cash drawer, USB HID scale, and Zebra ZPL label printer.","archived":false,"fork":false,"pushed_at":"2026-06-19T03:07:08.000Z","size":520,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-19T05:08:42.619Z","etag":null,"topics":["cash-drawer","escpos","fastapi","hardware-bridge","point-of-sale","python","receipt-printer","scale","usb-hid","warehouse","zebra","zpl"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hightower-systems.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-19T02:58:43.000Z","updated_at":"2026-06-19T03:07:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hightower-systems/station-hardware-agent","commit_stats":null,"previous_names":["hightower-systems/station-hardware-agent"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/hightower-systems/station-hardware-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hightower-systems%2Fstation-hardware-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hightower-systems%2Fstation-hardware-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hightower-systems%2Fstation-hardware-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hightower-systems%2Fstation-hardware-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hightower-systems","download_url":"https://codeload.github.com/hightower-systems/station-hardware-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hightower-systems%2Fstation-hardware-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35079376,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-03T02:00:05.635Z","response_time":110,"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":["cash-drawer","escpos","fastapi","hardware-bridge","point-of-sale","python","receipt-printer","scale","usb-hid","warehouse","zebra","zpl"],"created_at":"2026-07-03T08:34:25.653Z","updated_at":"2026-07-03T08:34:26.389Z","avatar_url":"https://github.com/hightower-systems.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Station Hardware Agent\n\n[![CI](https://github.com/hightower-systems/station-hardware-agent/actions/workflows/ci.yml/badge.svg)](https://github.com/hightower-systems/station-hardware-agent/actions/workflows/ci.yml)\n[![License: Apache 2.0](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](pyproject.toml)\n\nA small local HTTP agent that bridges a browser or cloud web app to the\nUSB hardware on a retail / warehouse station:\n\n- **ESC/POS receipt printer + cash drawer** (raw USB)\n- **USB HID shipping scale** (Mettler-Toledo / DYMO / OEM postal scales)\n- **Zebra ZPL label printer** (Windows print share)\n\nIt runs on the station's Windows machine, listens on `127.0.0.1`, and the\nweb app's browser tab calls it over loopback. Extracted and generalized\nfrom agents running daily in production stores.\n\n## Why this exists\n\nA web app served over HTTPS can't talk to a USB printer or scale -- the\nbrowser sandboxes pages away from local hardware. The fix is a local\nagent that owns the devices and exposes them on `http://127.0.0.1`, which\nthe page calls from the user's browser. This is that agent, with a\npluggable driver per device and an honest security model.\n\n## Devices\n\n| Driver | Device | Transport | Key routes |\n|---|---|---|---|\n| `escpos_usb` | ESC/POS receipt printer + cash drawer | raw USB (python-escpos / libusb) | `POST /print`, `POST /open-drawer` |\n| `hid_scale` | USB HID shipping scale | raw USB HID (hidapi) | `GET /scale` |\n| `zebra_zpl` | Zebra ZPL label printer | Windows print share (UNC) | `POST /label`, `POST /label/bin-sticker` |\n\nEnable the ones you need via `ENABLED_DRIVERS`. See [docs/devices.md](docs/devices.md).\n\n## How it works\n\n```\n  Web app (https://your-app)         The station machine\n  ----------------------------       ------------------------------------\n  browser tab  ──fetch http://127.0.0.1:8765/...──►  Station Hardware Agent\n                                                         ├─ escpos_usb  → receipt printer + drawer\n                                                         ├─ hid_scale   → USB HID scale\n                                                         └─ zebra_zpl   → Zebra label printer\n```\n\nDetails in [docs/architecture.md](docs/architecture.md).\n\n## Quick start\n\n### Windows (autostart, recommended)\n\n1. Install Python 3.11+ from python.org (tick **Add Python to PATH**).\n2. Copy this folder to the station, e.g. `C:\\station-hardware-agent\\`.\n3. Right-click `installers\\install.bat` -\u003e **Run as administrator**. It\n   creates a venv, installs the agent, copies `.env.example` to `.env`,\n   and registers a Task Scheduler entry that starts on every logon.\n4. Edit `.env` and set `ALLOWED_ORIGIN` (and the device ids you use).\n5. Start now without signing out:\n   `schtasks /Run /TN \"Station Hardware Agent\"`.\n\nFor a manual run instead, double-click `installers\\start_agent.bat`.\n\n### Any platform (dev)\n\n```bash\npip install -e \".[dev]\"\ncp .env.example .env        # then edit ALLOWED_ORIGIN\npython -m hwbridge          # or: uvicorn hwbridge.app:app\n```\n\n## ⚠ Browser setup is required\n\nChrome and Edge now block public-origin pages from reaching `127.0.0.1`\nunless Local Network Access is allowed for your site. **If you skip this,\na perfectly working agent will look broken.** Pick the tier that fits\n(flag, permission prompt, or the `LocalNetworkAccessAllowedForUrls`\nenterprise policy) in [docs/browser-setup.md](docs/browser-setup.md).\n\n## Configuration\n\nAll config is environment / `.env` (see [.env.example](.env.example)).\nThe only required value is `ALLOWED_ORIGIN`. Per-device keys are in\n[docs/devices.md](docs/devices.md).\n\n## HTTP API\n\n| Method | Path | Driver | Body / result |\n|---|---|---|---|\n| `GET` | `/status` | core | agent + per-driver liveness |\n| `POST` | `/print` | escpos_usb | `{format:\"text\", content, cut, open_drawer_after}` |\n| `POST` | `/open-drawer` | escpos_usb | (none) |\n| `POST` | `/test-print` | escpos_usb | prints a diagnostic slip |\n| `GET` | `/scale` | hid_scale | `{status, weight, unit:\"lbs\", stable}` |\n| `POST` | `/label` | zebra_zpl | raw ZPL bytes |\n| `POST` | `/label/bin-sticker` | zebra_zpl | `{sku, upc?}` |\n| `POST` | `/label/item-barcode` | zebra_zpl | `{upc, quantity}` |\n\nThe receipt printer prints **ESC/POS text** (not bitmaps); `/print` only\naccepts `format:\"text\"`.\n\n## Security model\n\n- **Loopback only** -- binds `127.0.0.1`, unreachable off the machine.\n- **Origin pin** -- every request must carry `Origin: \u003cALLOWED_ORIGIN\u003e`\n  or it's rejected `403`. No token (it would live in the browser anyway);\n  loopback + origin pin is the real boundary.\n\n## Development\n\n```bash\npip install -e \".[dev]\"\npytest\n```\n\nTests use fakes for every device, so no hardware (and no libusb/hidapi\nbackend) is needed to run them.\n\n## Project layout\n\n```\nhwbridge/\n  app.py            FastAPI factory + middleware + /status\n  config.py         settings (env / .env)\n  middleware.py     Private Network Access header (outermost)\n  tray.py           optional system-tray status icon\n  __main__.py       python -m hwbridge entrypoint\n  drivers/          one module per device + the registry\n  labels/zpl.py     ZPL label builders\ndocs/               architecture, devices, browser setup\ninstallers/         Windows install.bat / start_agent.bat\ntests/              hardware-free unit + app tests\n```\n\n## Status \u0026 platform\n\nBeta. Targeted at **Windows** stations (Task Scheduler autostart, cash\ndrawer, Zebra print share). The USB-HID and ESC/POS layers are\ncross-platform; the deployment story is Windows.\n\n## License\n\n[Apache 2.0](LICENSE). Extracted and generalized from production retail\nand warehouse station agents.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhightower-systems%2Fstation-hardware-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhightower-systems%2Fstation-hardware-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhightower-systems%2Fstation-hardware-agent/lists"}