Metadata-Version: 2.4
Name: superroute-sprint
Version: 0.1.5
Summary: sPrint, Superroute's printing SDK: find network, USB and Bluetooth printers, detect their language, print labels, PDF, HTML, images and raw bytes, and run a Superroute print node.
Author-email: Superroute <noreply@superroute.ca>
License: Superroute SDK License
Project-URL: Homepage, https://github.com/Goodneo-Solutions/sprint-releases
Keywords: printing,label,thermal,zpl,escpos,superroute
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Topic :: Printing
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# superroute-sprint

sPrint for Python: Superroute's printing SDK. Find network, USB and Bluetooth
printers, detect their command language (ZPL, TSPL, ESC/POS, CPCL and the vendor
dialects), print labels, PDF, HTML, images and raw bytes, and turn the machine
into a Superroute print node. The wheels carry the native sPrint library for
Linux (x86-64, arm64, armv7; glibc 2.17+), macOS 13+ (arm64, x86-64) and Windows
(x64, arm64); nothing is compiled when installing.

```python
from superroute_sprint import (PrinterRegistry, TargetPrinter, LabelJob, PrintJob, Discovery,
                               PrintNode, NodeState, Languages, Transports, JobTypes)

with PrinterRegistry("printers.json") as printers:
    printers.save(TargetPrinter(name="Labels", host="192.168.1.40", transport=Transports.NETWORK,
                                language=Languages.ZPL))
    result = printers.print(PrintJob(type=JobTypes.LABEL, label=LabelJob.parse(label_json)))
    if not result.ok:
        print(result.reason, result.message)

for p in Discovery.scan_network():
    print(p.name, p.host)

node = PrintNode(printers, state=saved_state, on_event=lambda e: save_if_state(e))
node.pair("K2M9XY")          # the code from the Print Nodes page
node.start()
```

### Print node hooks

A host app can answer remote commands itself, read and apply what the server sets per printer,
add heartbeat fields and show the jobs in flight (docs/NODE-HOOKS.md):

```python
from superroute_sprint import CommandAnswer

def on_command(cmd):                          # on a worker thread; None leaves it to the node
    if cmd.action == "connectivity_test":
        return CommandAnswer(output=check_server())
    return None

node = PrintNode(printers, state=saved_state, on_event=on_event,
                 on_command=on_command, commands_every=15)
# on_event also gets kind "settings" (e.settings: languages, locks, default papers — already
# applied; a locked language is refused by PrinterRegistry.save) and kind "printing"
# (e.printing: a cloud or peer job started / ended).
node.printer_settings().language_locked("Label")
refused = node.push_languages({"Label": "zpl"})                       # a local pick
node.push_languages({"Label": "cpcl"}, corrections=["Label"])         # the printer's own answer
node.set_printer_fields("Label", {"language_kept": {"language": "zpl", "since": since, "jobs": 12}})
node.printing()                                                        # jobs in flight
media = SPrint.query_zpl_media(zebra)        # ZplMedia(dpi, width_mm, length_mm, ...) or None
```

## LAN peer printing

Two devices on the same network print to each other's shared printers with no server in
between (the SuperPrinter apps' peer-direct protocol). A host shares nothing until it names
its printers, and admits peers in approval mode unless told otherwise; sPrint keeps no files
for peers, so store the state it hands over.

```python
from superroute_sprint import (PeerHost, PeerHostState, PeerIdentity, PeerSession, PeerModes,
                               Discovery, PrintJob, JobTypes)

# The printer owner
def on_peer(e):
    if e.kind == "peer_state":
        save(e.state.json)                      # identity, mode, shared printers, trust list
    elif e.kind == "peer_pending":
        host.decide(e.pending.id, ask_owner(e.pending.name, e.pending.fingerprint, e.pending.note))

host = PeerHost(printers, state=PeerHostState(saved_json), name="Front desk", on_event=on_peer)
host.set_shared(["Labels"])
host.set_discoverable(True)                     # advertised over mDNS
host.start()

# The printer user
me = PeerIdentity.from_seed(saved_seed)
peer = Discovery.browse_peers()[0]
session = PeerSession.connect(me, peer.addr, fingerprint=peer.fingerprint, note="Packing desk",
                              on_event=lambda e: print("ended:", e.reason))
if session.status.status == "pending":
    session.wait_approval()                     # SPrintError code "denied" / "timeout"
result = session.print("Labels", PrintJob(type=JobTypes.LABEL, label=label))
printers.attach_peer(session)                   # or route jobs to "peer:<fingerprint>/Labels"
```

Licensed under the Superroute SDK License.
