Skip to main content

Python client for Seymour masking screens, connected via direct serial or Global Caché iTach IP2SL

Project description

seymourlib

CI Coverage PyPI License: MIT

Python client for Seymour masking screens, connected via direct serial or Global Caché iTach IP2SL. Built for rock-solid control loops, Home Assistant integrations, and quick bench testing. 😎


Highlights

  • Async-first client and transport abstractions (TCP/IP2SL vs native serial) with consistent APIs.
  • Protocol helpers that mirror the official Seymour RS232 spec, including parsing/validation utilities.
  • seymourctl CLI for one-off commands, scripting, and smoke tests in CI.
  • Zero-config Global Caché IP2SL and serial-port discovery via async helpers and CLI subcommands.
  • Movement/preset commands poll controller status and return only once the motors report HALTED/STOPPED, so scripts never race ahead.
  • Batteries-included retry logic (tenacity), timeout handling, and graceful cancellation via anyio.

Architecture at a Glance

flowchart TB
     App[Your automation / HA stack] -->|async API| Client[SeymourClient]
     Client --> Protocol[Protocol helpers]
     Client --> Transport
     Transport -->|TCP 4999| IP2SL[Global Caché IP2SL]
     Transport -->|RS232| Screen[Seymour Masking Screen]
     IP2SL -->|RS232| Screen

Installation

Requirements

  • Python 3.11+
  • uv >= 0.9 (preferred) or classic pip

Quick install (recommended)

uv tool install --python 3.11 "seymourlib[serial]"
  • This pulls the published wheel straight from PyPI and drops a seymourctl executable anywhere on your PATH.
  • Use seymourctl --help to confirm things are wired up, then jump straight to the CLI examples below.

Existing virtual environments

Already have a project venv or uv workspace? Install directly:

uv add "seymourlib[serial]"

This will update your project's dependencies, install the latest source distribution of seymourlib, and update whatever lockfiles your project may use.

💡 The optional serial extra pulls in pyserial-asyncio so the same client works over USB/RS232 without the IP bridge. If you want to trim your project's dependency graph and never plan to talk over direct RS232, you can skip it.

Classic pip fallback

python -m venv .venv
. .venv/bin/activate  # or .venv\Scripts\activate on Windows
pip install "seymourlib[serial]"

Local Development

To debug, contribute code, or run the full test suite:

  1. Clone & bootstrap
    • git clone https://github.com/richard-berg/seymourlib.git
    • cd seymourlib
    • uv sync --all-extras
  2. Sanity-test the library
    • uv run pytest for local regression.
    • SEYMOUR_HOST=<HOSTNAME> uv run seymourctl -v status to hit your target once hardware is reachable.
  3. Wire up hardware
    • Confirm straight-through RS232 between IP2SL and the Seymour control port.
    • For direct USB serial, a FTDI-based adapter keeps timing stable.
  4. Pick your transport
    • TCPTransport(host, port=4999) for IP2SL.
    • SerialTransport(port="COM5") for direct connection (requires [serial]).

Usage Examples

Python API

import asyncio
from seymourlib.client import SeymourClient
from seymourlib.transport import TCPTransport

async def main() -> None:
     async with SeymourClient(TCPTransport("192.168.1.70")) as client:
          status = await client.get_status()
          print(status)

asyncio.run(main())

CLI

seymourctl --host 192.168.1.70 status
seymourctl --host 192.168.1.70 preset apply 235
seymourctl --help

Motion-oriented commands such as calibrate, positions in/out/home, and preset apply block until the controller reports HALTED or STOPPED_AT_RATIO, keeping CI and automation flows deterministic without manual sleep calls.

Transport discovery (Python API)

import asyncio
from seymourlib.discovery import (
    enumerate_serial_transports,
    enumerate_tcp_transports,
)


async def main() -> None:
    tcp_devices = await enumerate_tcp_transports()  # listens for Global Caché beacons
    serial_ports = await enumerate_serial_transports()
    print("TCP devices:")
    for device in tcp_devices:
        print(device.host, device.metadata.get("Model", ""))

    print("Serial ports:")
    for port in serial_ports:
        print(port.device, port.description)


asyncio.run(main())

enumerate_tcp_transports() joins the Global Caché multicast group and returns deduplicated IP2SL candidates (override interval to listen longer or interface_ip to bind a specific NIC). enumerate_serial_transports() surfaces every local serial adapter with the proper Seymour baud rate by default.

Transport discovery (CLI)

seymourctl discover tcp
seymourctl discover serial

Use discover tcp when you need to confirm IP2SL devices are visible on the LAN; the table output includes the advertised model, status, and UUID from the Global Caché beacons. discover serial lists local USB/RS232 adapters with hardware IDs so you can select the right port before launching the client.


IP2SL Setup & Diagnostics

1. Test direct serial first

  • Connect a laptop directly to the Seymour RS232 port with a known-good USB adapter.
  • Use RealTerm, CoolTerm, or any tty tool (115200 8N1 by default - verify via Seymour docs) to send a PS? (position status) command.
  • Once commands succeed locally, you know the projector + cable + command syntax are correct before adding the network hop.

2. Discover the IP2SL via iHelp

  • Download Global Caché iHelp and run it on the same subnet.
  • Press Scan to locate the IP2SL; note the MAC, firmware, and current IP.
  • If nothing shows up, temporarily disable host firewalls or plug directly into a laptop + small DHCP scope.

3. Pin the network configuration

  • Point a browser at http://<your-ip>/ (from step 2) if you want a point-and-click GUI for DHCP/static IP, firmware, and reboot controls.
  • Otherwise, install Global Caché iTest.
    • Use iTest or telnet into port 4998 (the configuration/control port).
    • Send set dhcp 0, set ip <static>, set mask <subnet>, set gateway <gw>, then save to burn settings.
  • Reboot (power cycle or reboot command) and confirm the device responds on the static IP.
  • Document the MAC/IP in your DHCP reservations to avoid future collisions.

4. Lock the serial parameters

  • Open the IP2SL web UI and switch to the Serial tab, or telnet/iTest into port 4998 for command-line configuration.
  • Ensure the port is set to 115200 baud, 8 data bits, no parity, 1 stop bit to match Seymour’s RS232 spec.
  • Saving via the UI writes immediately; if you used the control port, run set baud 115200, set data 8, set parity 0, set stop 1, then save and reboot so the bridge always boots with the correct framing.

5. Exercise the serial bridge with iTest

  • Open iTest (or telnet)
  • Target port 4999 on the static IP, choose RAW mode, and click Connect.
  • Send a few simple commands (e.g. [01S], [01P]). The response should echo immediately.
  • If latency creeps in, verify telnet keep-alives/device busy LEDs. Keep the window open while you walk through automation flows to watch the live traffic.

6. Promote to seymourlib

  • Update your .env / config with the same host/port verified above.
  • Start with uv run seymourctl -v status (verbose logging shows full request/response frames).
  • Flip to automation (Home Assistant, Homebridge, etc.) once CLI calls are boringly reliable.

Troubleshooting & Field Notes

  • No response over TCP but serial works - Ensure port 4999 is open on local firewalls and that the IP2SL LED blinks on connect; if not, recheck the static IP settings from step 3.
  • 🔌 Commands hang after a day - The IP2SL can queue stale sockets; send set rs232disconnect 1 over port 4998 so idle TCP clients auto-close.
  • 🔁 Race conditions from HA automations - Wrap your automations with seymourlib's async context manager so only one command pipeline exists per transport.
  • 🧪 Need deeper diagnostics - Add --verbose to seymourctl to dump protocol frames, or enable debug logging to capture per-request timestamps.
  • 🛠️ Firmware drift - Global Caché publishes release notes; mismatched firmware sometimes defaults back to DHCP on reboot. Always export a config snapshot in iHelp after upgrades.

Related Docs & Inspiration


Contributing

  • Fork, create a feature branch, and open a PR (tests + type checks 🚦 required).
  • pre-commit run before pushing.
  • Issues and hardware findings are welcome - real-world serial logs are gold for regression tests.

Need something else? Open a discussion or ping via Issues and we’ll figure it out together. 🙌

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

seymourlib-0.1.4.tar.gz (17.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

seymourlib-0.1.4-py3-none-any.whl (20.7 kB view details)

Uploaded Python 3

File details

Details for the file seymourlib-0.1.4.tar.gz.

File metadata

  • Download URL: seymourlib-0.1.4.tar.gz
  • Upload date:
  • Size: 17.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","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}

File hashes

Hashes for seymourlib-0.1.4.tar.gz
Algorithm Hash digest
SHA256 637f15d7ed0709f321c5019027e29224e827ebf40003c72ba13a48255aec6671
MD5 c6812750f78098d1b32ebeabbce928ea
BLAKE2b-256 9484a09e62967e23a35d720aaaeba1781d52e3db8d1e417c5ec41bde692942db

See more details on using hashes here.

File details

Details for the file seymourlib-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: seymourlib-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 20.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","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}

File hashes

Hashes for seymourlib-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 ee3c07ac26c60dba70ed15d233f00248d15bf88475fea90c83e1e23d596d2e86
MD5 c3c84d3bdc0ecb3527a63e287cb69604
BLAKE2b-256 54d8a04e46a8d028c2ad5374abb0484b32acd41f02de690c66008e54ec49e85f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page