Expand description
§pispas_modules — Local Pispas service for Windows POS
This crate is the main runtime binary of the Pispas installer. It runs
as a Windows background service (installed by pispas-service.exe) and
exposes a single modular WebSocket endpoint that the Pispas web/desktop
clients talk to for printing, scale reads, RFID reads, card payments,
cash drawer control, kitchen order dispatching, etc.
The crate is pispas-modules on crates (see Cargo.toml), but Rust
renames hyphens to underscores so everything imports as pispas_modules.
§High-level architecture
+----------------------+ +----------------------------+
| Pispas web/mobile UI | | Pispas tray-app (Windows) |
| (app.unpispas.es) | | [pispas-tray-app.exe] |
+----------+-----------+ +-------------+--------------+
| |
| wss://local.unpispas.es:5005 | IPC (named pipe / WS)
| (or ws:// fallback) |
v v
+-------------------------------------------------------------+
| pispas-modules.exe (THIS CRATE) |
| Dual-mode WebSocket server (TLS + plain on same TCP port) |
| |
| +---------+ +---------+ +---------+ +---------+ +----+ |
| | BASE | | PRINT | | SCALE | | RFID | | … | |
| +---------+ +---------+ +---------+ +---------+ +----+ |
| |
| +------------+ +----------+ +--------+ +-------------+ |
| | CASH_GUARD | | PAYTEF | | MYPOS | | ORDER_KITC… | |
| +------------+ +----------+ +--------+ +-------------+ |
| |
| +--------------+ +------------+ |
| | command_view | | persistence| |
| +------+-------+ +------------+ |
+---------|---------------------------------------------------+
|
| spawns a sidecar web server on localhost:9000-ish
v
+----------------------------------------+
| command_viewer HTTP/WS (localhost only)|
| static HTML UI for ops / diagnostics |
+----------------------------------------+pispas_modules is the service — the other binaries in the workspace
orchestrate around it:
pispas-installerinstalls this binary as a Windows service and registers the scheduled tasks, certificates, firewall rules, etc.pispas-serviceWindows-service wrapper (launchespispas-modules.exeand handles the Service Control Manager life-cycle).pispas-elevatorUAC-elevated helper (seeCLAUDE.md §6).pispas-tray-appTray-icon app in the system tray that communicates with this service over a local IPC channel, shows status and exposes quick actions.pispas-configurator-htmlHTML configurator UI that writes to the.envconsumed byConfigEnv::load.pispas-order-kitchenDedicated order-kitchen display process (separate crate; this crate’sorder_kitchenmodule is the backend that feeds it).
§Network surface
Every socket the service opens (all loopback-only, never 0.0.0.0):
| Socket | What it is | Notes |
|---|---|---|
local.unpispas.es:5005 | Main dual-mode WebSocket endpoint | TLS + plain on the same TCP port. See start_local_server. local.unpispas.es is an /etc/hosts-style entry installed by the installer that resolves to 127.0.0.1. |
<remote>:8765 (out-bound) | Remote gateway client | Only when a REMOTE_HOST is configured. See start_remote_server. |
127.0.0.1:8081 (HTTP) | command_viewer landing page | Static UI static/index.html. Localhost-only. |
127.0.0.1:9001 (WS) | command_viewer WebSocket | Receives ticket/command events and forwards to subscribed printers. |
Port numbers are defaults; all are configurable through ConfigEnv
(see sharing::utils::ConfigEnv).
§TLS and local.unpispas.es
The service binds to 127.0.0.1 but clients connect using
https:// / wss://local.unpispas.es:<port>. This is because:
- The cert embedded in the binary (
cert.pem+key.pem) is a CloudFlare Origin cert issued for*.unpispas.es. Clients only trust it if the hostname they connect to matches that SAN. local.unpispas.esis added to the systemhostsfile by the installer, resolving to127.0.0.1(and also to the LAN IP, so other devices on the same network can reach this service).- Chrome’s Private Network Access policy blocks
https→httpmixed-scheme requests to loopback; serving TLS end-to-end avoids that.
The dual-mode listener inspects the first byte of each accepted
connection: 0x16 means a TLS ClientHello (wrap in TlsAcceptor),
otherwise treat as plain WebSocket. See the detailed flow in
utils::start_local_server.
§Message protocol
Every request is a JSON object with at least:
{
"UUIDV4": "7c3f…",
"TARGET": "PRINT",
"ACTION": "..."
}The server routes on TARGET to one of the modules listed in
Modules. The reply is:
{
"SERVICE_NAME": "<module>",
"SERVICE_VERS": "1.0.0",
"MESSAGE_TYPE": "RESPONSE",
"MESSAGE_EXEC": "SUCCESS" | "FAILURE",
"MESSAGE_UUID": "7c3f…", // echoed from request.UUIDV4
"MESSAGE_DATA": <action result>
}MESSAGE_UUID always echoes the request’s UUIDV4 so clients can
match responses to requests over the same socket (multiple in-flight
requests are allowed).
§Modules
Each public module below is registered in utils::load_services and
picks a TARGET string that clients use to address it.
TARGET | Module | What it does |
|---|---|---|
BASE | base | Housekeeping: CHECK (handshake sanity), PING (keep-alive), VERSION, CONFIG. |
PRINT | printsrvc | The whole ESC/POS printing pipeline: discover printers, render HTML → PDF → raster → ESC/POS, send to USB / network / Bluetooth / Windows spooler. Also getPrinters returns the list of installed printers on Windows. |
SCALE | scale | Reads a COM-port scale (weight, tare, zero). |
RFID | rfid | Reads an RFID tag from a configured reader. |
CASHGUARD | cash_guard | Cash-drawer control via the CashGuard HTTP API (open, balance, status). |
PAYTEF | paytef | Card-payment flow through Paytef terminals. |
MYPOS | mypos | Card-payment flow through MyPOS terminals. |
ORDER_KITCHEN | order_kitchen | Feeds tickets to the pispas-order-kitchen display app over IPC. |
CACHE | persistence | Local key/value blob stored on disk (file.bin) so printing survives server hiccups. See sharing::PERSISTANCE_FILE_NAME. |
| — (side-car) | command_viewer | Not a TARGET. Spawns an HTTP + WS server on localhost for an in-house ops/diagnostics UI (static/) that lets support staff see incoming commands in real time and re-send them to printers. |
§Service and tray-app interaction
The tray-app (pispas-tray-app.exe) is a stand-alone Windows program
that sits in the system tray. It connects to this service over the
same WebSocket (local.unpispas.es:5005) and issues BASE / CHECK
pings to show service health, exposes a right-click menu to open the
configurator, and surfaces notifications when a printer fails.
The configurator (pispas-configurator-html.exe) is a one-shot program
launched from the tray: it shows a local HTML UI (bundled in
binaries/configurator_html/dist), reads/writes the .env that backs
sharing::utils::ConfigEnv,
and restarts the service when the user saves.
§Lifecycle
main.rscreates the install directory, initializes logging (easy_trace), and callsConfigEnv::loadto materialize the configuration from.env.utils::load_servicesreadsMODULES(env var, default"base,print,scale,rfid") and instantiates the correspondingServiceimplementations into aHashMap<String, Arc<dyn Service>>.utils::start_local_serverbinds TCP127.0.0.1:<local_port>and accepts both TLS and plain clients, dispatching each connection toutils::websocket_handler.- If a
REMOTE_HOSTis configured,utils::start_remote_serveropens an outbound WebSocket acting as a gateway client (tunnels commands coming from the cloud back into this service). - Incoming WS frames are JSON-decoded, routed by
TARGETthrough the services map, and the response is sent back on the same socket.
§What is (re-)exported
Everything in prelude is flattened at the crate root via
pub use self::prelude::*;, so downstream binaries (main.rs,
pispas-service, tests) can just use pispas_modules::*;.
Re-exports§
pub use self::prelude::*;
Modules§
- base
- cash_
guard - command_
viewer - mypos
- order_
kitchen - paytef
- pdf_
manager - persistence
- prelude
- One-stop re-export hub.
use pispas_modules::prelude::*;pulls every public item of every module into scope at once. - printsrvc
- rfid
- scale
- service
- utils