Skip to main content

vention-barcode-scanner

Async barcode scanner fleet manager for Vention industrial automation. Unified Scanner ABC over Keyence TCP, USB HID (evdev), and mock backends.

Scanner Types

Type Protocol Platform Use Case
KeyenceScanner Async TCP (port 9004) Any Keyence SR-series (SR-1000, SR-2000, SR-5000)
EvdevScanner Linux USB (evdev) Linux USB keyboard-emulating barcode readers
MockScanner In-memory Any Simulation and testing

Usage

This is an async library: every scanner call uses await, so it must run inside an async def you start with asyncio.run(...). (await at the top level of a script raises SyntaxError: 'await' outside function.)

Quickstart — no hardware (mock mode)

Runs as-is, no scanner connected. mode="mock" swaps in in-memory scanners; mock_label_probability=1.0 makes every scan return a label so the demo is deterministic.

import asyncio

from barcode_scanner.models import ScannerConfig, ScannerFleetConfig
from barcode_scanner.service import ScannerService

config = ScannerFleetConfig(
    scanners=[
        ScannerConfig(id="s1", host="192.168.7.100", location_id="station-a"),
    ],
    mock_label_probability=1.0,  # always "read" a label (drop to taste, e.g. 0.3)
    mock_labels=["GT-205"],
)
service = ScannerService.from_config(config, mode="mock")


async def main():
    await service.connect_all()
    result = await service.scan("station-a")  # one scan window open→dwell→close
    await service.disconnect_all()

    print(result.status)  # ScanStatus.OK | NO_READ | TIMEOUT | ERROR
    print(result.label_detected)  # True / False
    print(result.label_string)  # "GT-205" or None


asyncio.run(main())  # runs everything in main()

Connecting real hardware

Same code — swap mode="mock" for mode="real" and pick the backend. host is each scanner's IP; location_id is the name you scan by.

service = ScannerService.from_config(config, mode="real", scanner_type="keyence")
#                                          ^ "keyence" (TCP) | "evdev" (USB, Linux)

Label Validation

Optional callback to reject invalid labels at the scanner layer:

def validate_label(label: str) -> bool:
    return label.startswith("GT-") and len(label) <= 20


service = ScannerService.from_config(config, label_validator=validate_label)
# Labels that fail validation are downgraded to NO_READ

Metrics

metrics = service.get_metrics()["s1"]
metrics.total_scans  # 1234
metrics.success_rate  # 0.89
metrics.avg_scan_ms  # 45.2

Tuning and Diagnostics

await service.auto_tune("station-a")  # One-shot FTUNE + SAVE
await service.tune("station-a", bank=0)  # Interactive TUNE per bank + TQUIT
status = await service.get_scanner_status("station-a")
# {"busy": 0, "last_cmd": 0, "error": 0}       # BUSYSTAT / CMDSTAT / ERRSTAT

Structured Logging

from barcode_scanner.logger import set_log_callback


def on_scanner_log(code, source, level, message):
    mqtt_publish("scanner/logs", {"code": code, "source": source, "message": message})


set_log_callback(on_scanner_log)

Keyence Protocol

TCP port 9004. ASCII commands terminated with \r.

Scan sequence: LON\r (open scan window) -> dwell -> LOFF\r (close window) -> read response. The scanner only sends data after LOFF.

Command Response Purpose
LON\r barcode or ERROR\r Open scan window (default bank)
LON,01\r barcode or ERROR\r Open scan window (bank 1)
LOFF\r -- Close scan window
BCLR\r OK\r Clear read buffer
RESET\r OK\r Reset scanner (reboots, drops TCP)
FTUNE\r OK,FTUNE\r then result One-shot auto-focus calibration
TUNE,00\r OK\r Start interactive tuning (bank 0)
TQUIT\r OK\r Stop tuning and save
SAVE\r OK\r Persist settings across power cycles
BUSYSTAT\r 0/1/2 Query busy state (idle/reading/tuning)
CMDSTAT\r 0/1/2 Query last command result
ERRSTAT\r 0/1/2 Query hardware error state

API

ScannerService

class ScannerService:
    @classmethod
    def from_config(cls, config, mode="real", scanner_type="keyence",
                    label_validator=None) -> ScannerService

    async def scan(self, location_id, timeout=None, bank=None) -> ScanResult
    async def connect_all(self) -> dict[str, bool]
    async def disconnect_all(self) -> None
    async def reset(self, location_id) -> bool
    async def reset_all(self) -> dict[str, bool]
    async def auto_tune(self, location_id) -> bool
    async def tune(self, location_id, bank=0) -> bool
    async def get_scanner_status(self, location_id) -> dict
    def get_metrics(self) -> dict[str, ScanMetrics]
    def get_metrics_summary(self) -> dict

ScanResult

class ScanResult:
    status: ScanStatus  # OK | NO_READ | TIMEOUT | ERROR
    label_detected: bool
    label_string: str | None
    scanner_id: str
    error: str | None

Scanner ABC

class Scanner(ABC):
    async def scan(self, timeout=None, bank=None) -> ScanResult
    async def connect(self) -> bool
    async def disconnect(self) -> None
    async def reset(self) -> bool
    async def auto_tune(self) -> bool
    async def tune(self, bank=0) -> bool
    async def get_status(self) -> dict
    connected: bool  # property

Development

cd barcode-scanner
uv sync
make test          # 115 tests
make lint          # ruff check + format
make type-check    # pyright

Metadata

Release files for vention-barcode-scanner 0.8.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vention-barcode-scanner 0.8.3
File Size Uploaded Provenance Actions
vention_barcode_scanner-0.8.3.tar.gz 29.4 kB Without provenance Details for vention_barcode_scanner-0.8.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for vention-barcode-scanner 0.8.3
File Interpreter ABI Platform Actions
vention_barcode_scanner-0.8.3-py3-none-any.whl Python 3 none any Details for vention_barcode_scanner-0.8.3-py3-none-any.whl

Total release size: 57.8 kB

Release files / vention_barcode_scanner-0.8.3.tar.gz

Download URL vention_barcode_scanner-0.8.3.tar.gz
Size 29.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8d1aa879aedd42106f131694c364c9eeaf12788500badd68acb1b35c09ae83b1
BLAKE2b-256 checksum
How to use checksums
8c3f2274156415ef92c0355b0725f41482c4c2fa701c0af812b72d7540f82477
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / vention_barcode_scanner-0.8.3-py3-none-any.whl

Download URL vention_barcode_scanner-0.8.3-py3-none-any.whl
Size 28.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b943e3e7ba12fd179ace7b3e89df814fa19c0ad86f14734b36902c6b2931eedd
BLAKE2b-256 checksum
How to use checksums
1b1fab29acfd30d61f20872eea375c18c67e8e6d156d75d0ee558c8cef852c2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for vention-barcode-scanner 0.8.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page