Crate pispas_modules

Crate pispas_modules 

Source
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-installer installs this binary as a Windows service and registers the scheduled tasks, certificates, firewall rules, etc.
  • pispas-service Windows-service wrapper (launches pispas-modules.exe and handles the Service Control Manager life-cycle).
  • pispas-elevator UAC-elevated helper (see CLAUDE.md §6).
  • pispas-tray-app Tray-icon app in the system tray that communicates with this service over a local IPC channel, shows status and exposes quick actions.
  • pispas-configurator-html HTML configurator UI that writes to the .env consumed by ConfigEnv::load.
  • pispas-order-kitchen Dedicated order-kitchen display process (separate crate; this crate’s order_kitchen module is the backend that feeds it).

§Network surface

Every socket the service opens (all loopback-only, never 0.0.0.0):

SocketWhat it isNotes
local.unpispas.es:5005Main dual-mode WebSocket endpointTLS + 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 clientOnly when a REMOTE_HOST is configured. See start_remote_server.
127.0.0.1:8081 (HTTP)command_viewer landing pageStatic UI static/index.html. Localhost-only.
127.0.0.1:9001 (WS)command_viewer WebSocketReceives 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.es is added to the system hosts file by the installer, resolving to 127.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 httpshttp mixed-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.

TARGETModuleWhat it does
BASEbaseHousekeeping: CHECK (handshake sanity), PING (keep-alive), VERSION, CONFIG.
PRINTprintsrvcThe 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.
SCALEscaleReads a COM-port scale (weight, tare, zero).
RFIDrfidReads an RFID tag from a configured reader.
CASHGUARDcash_guardCash-drawer control via the CashGuard HTTP API (open, balance, status).
PAYTEFpaytefCard-payment flow through Paytef terminals.
MYPOSmyposCard-payment flow through MyPOS terminals.
ORDER_KITCHENorder_kitchenFeeds tickets to the pispas-order-kitchen display app over IPC.
CACHEpersistenceLocal key/value blob stored on disk (file.bin) so printing survives server hiccups. See sharing::PERSISTANCE_FILE_NAME.
— (side-car)command_viewerNot 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

  1. main.rs creates the install directory, initializes logging (easy_trace), and calls ConfigEnv::load to materialize the configuration from .env.
  2. utils::load_services reads MODULES (env var, default "base,print,scale,rfid") and instantiates the corresponding Service implementations into a HashMap<String, Arc<dyn Service>>.
  3. utils::start_local_server binds TCP 127.0.0.1:<local_port> and accepts both TLS and plain clients, dispatching each connection to utils::websocket_handler.
  4. If a REMOTE_HOST is configured, utils::start_remote_server opens an outbound WebSocket acting as a gateway client (tunnels commands coming from the cloud back into this service).
  5. Incoming WS frames are JSON-decoded, routed by TARGET through 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