chainway-serial 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daan Vervacke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.4
2
+ Name: chainway-serial
3
+ Version: 0.1.0
4
+ Summary: Asynchronous Python library for Chainway UR4 UHF RFID readers over serial and TCP
5
+ Keywords: chainway,ur4,uhf,rfid,epc,gen2,serial,tcp,serialx,asyncio,home-assistant
6
+ Author: Daan Vervacke
7
+ Author-email: Daan Vervacke <daan.vervacke@proton.me>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: AsyncIO
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Topic :: System :: Hardware
15
+ Classifier: Typing :: Typed
16
+ Requires-Dist: serialx>=1.10
17
+ Requires-Python: >=3.14
18
+ Project-URL: Homepage, https://github.com/DaanVervacke/chainway-serial
19
+ Project-URL: Repository, https://github.com/DaanVervacke/chainway-serial
20
+ Project-URL: Issues, https://github.com/DaanVervacke/chainway-serial/issues
21
+ Project-URL: Changelog, https://github.com/DaanVervacke/chainway-serial/blob/main/CHANGELOG.md
22
+ Project-URL: Documentation, https://chainway-serial.readthedocs.io/
23
+ Description-Content-Type: text/markdown
24
+
25
+ # chainway-serial
26
+
27
+ [![Check](https://github.com/DaanVervacke/chainway-serial/actions/workflows/check.yml/badge.svg)](https://github.com/DaanVervacke/chainway-serial/actions/workflows/check.yml)
28
+ [![PyPI](https://img.shields.io/pypi/v/chainway-serial.svg)](https://pypi.org/project/chainway-serial)
29
+ [![Python](https://img.shields.io/pypi/pyversions/chainway-serial.svg)](https://pypi.org/project/chainway-serial)
30
+ [![License](https://img.shields.io/pypi/l/chainway-serial.svg)](https://github.com/DaanVervacke/chainway-serial/blob/main/LICENSE)
31
+
32
+ Asynchronous Python library for the [Chainway UR4](https://www.chainway.net/) fixed UHF RFID reader, over RS-232 and TCP, built on [serialx](https://github.com/puddly/serialx). Requires Python >= 3.14.
33
+
34
+ ```bash
35
+ uv add chainway-serial
36
+ ```
37
+
38
+ or:
39
+
40
+ ```bash
41
+ pip install chainway-serial
42
+ ```
43
+
44
+ ```python
45
+ import asyncio
46
+
47
+ from chainway_serial import ChainwayClient
48
+
49
+
50
+ async def main() -> None:
51
+ async with ChainwayClient("socket://192.168.99.200:8888") as client:
52
+ print(await client.get_version())
53
+
54
+ async for tag in client.inventory():
55
+ print(tag.epc.hex(), tag.rssi, tag.antenna)
56
+
57
+
58
+ asyncio.run(main())
59
+ ```
60
+
61
+ ## Scope
62
+
63
+ | Area | Coverage |
64
+ |---|---|
65
+ | Transports | Any serialx URL: device paths, `socket://`, `rfc2217://`, ESPHome proxies |
66
+ | Status | Firmware, STM32 and hardware versions, device ID, temperature, return loss, antenna connection state, battery |
67
+ | RF | Per-antenna read and write power, region, fixed frequency, Gen2 parameters, RF link, FastID, TagFocus, fast inventory mode, carrier wave |
68
+ | Inventory | Mode selection, tag filter, single and continuous inventory with phase reporting, tag callbacks |
69
+ | Tag operations | Read, write, block write, block erase, lock, kill, authenticate, block permalock, with tag filters |
70
+ | Collected tags | Batch pull, counts, delete, flash pull, for auto and trigger work modes |
71
+ | Configuration | Reader and destination addresses, work modes, trigger timing, buzzer, volume, GPO, antennas, software and factory reset |
72
+ | Peripherals | Barcode imager, buzzer, LED |
73
+ | Firmware | Bootloader jump and the update block flow |
74
+ | Discovery | UDP discovery broadcast listener |
75
+
76
+ ## Protocol status
77
+
78
+ The wire protocol is reverse engineered from the vendor Android, Java and Windows SDKs, cross-checked against the vendor's official protocol document. Every command of the document is implemented, including its module-level subset. No command has been verified against live hardware yet. The complete byte level reference, with every decoded payload layout and the unverified items, lives in [docs/protocol.md](docs/protocol.md). When a reader is available, `uv run python scripts/probe_chainway.py socket://192.168.99.200:8888` exercises every command and writes the responses to `captures/`.
79
+
80
+ While a continuous inventory runs, the reader answers no command except stop inventory. The client models this: other commands raise `ChainwayInventoryActiveError` until the scan ends.
81
+
82
+ ## Documentation
83
+
84
+ The full documentation is on [Read the Docs](https://chainway-serial.readthedocs.io/).
@@ -0,0 +1,60 @@
1
+ # chainway-serial
2
+
3
+ [![Check](https://github.com/DaanVervacke/chainway-serial/actions/workflows/check.yml/badge.svg)](https://github.com/DaanVervacke/chainway-serial/actions/workflows/check.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/chainway-serial.svg)](https://pypi.org/project/chainway-serial)
5
+ [![Python](https://img.shields.io/pypi/pyversions/chainway-serial.svg)](https://pypi.org/project/chainway-serial)
6
+ [![License](https://img.shields.io/pypi/l/chainway-serial.svg)](https://github.com/DaanVervacke/chainway-serial/blob/main/LICENSE)
7
+
8
+ Asynchronous Python library for the [Chainway UR4](https://www.chainway.net/) fixed UHF RFID reader, over RS-232 and TCP, built on [serialx](https://github.com/puddly/serialx). Requires Python >= 3.14.
9
+
10
+ ```bash
11
+ uv add chainway-serial
12
+ ```
13
+
14
+ or:
15
+
16
+ ```bash
17
+ pip install chainway-serial
18
+ ```
19
+
20
+ ```python
21
+ import asyncio
22
+
23
+ from chainway_serial import ChainwayClient
24
+
25
+
26
+ async def main() -> None:
27
+ async with ChainwayClient("socket://192.168.99.200:8888") as client:
28
+ print(await client.get_version())
29
+
30
+ async for tag in client.inventory():
31
+ print(tag.epc.hex(), tag.rssi, tag.antenna)
32
+
33
+
34
+ asyncio.run(main())
35
+ ```
36
+
37
+ ## Scope
38
+
39
+ | Area | Coverage |
40
+ |---|---|
41
+ | Transports | Any serialx URL: device paths, `socket://`, `rfc2217://`, ESPHome proxies |
42
+ | Status | Firmware, STM32 and hardware versions, device ID, temperature, return loss, antenna connection state, battery |
43
+ | RF | Per-antenna read and write power, region, fixed frequency, Gen2 parameters, RF link, FastID, TagFocus, fast inventory mode, carrier wave |
44
+ | Inventory | Mode selection, tag filter, single and continuous inventory with phase reporting, tag callbacks |
45
+ | Tag operations | Read, write, block write, block erase, lock, kill, authenticate, block permalock, with tag filters |
46
+ | Collected tags | Batch pull, counts, delete, flash pull, for auto and trigger work modes |
47
+ | Configuration | Reader and destination addresses, work modes, trigger timing, buzzer, volume, GPO, antennas, software and factory reset |
48
+ | Peripherals | Barcode imager, buzzer, LED |
49
+ | Firmware | Bootloader jump and the update block flow |
50
+ | Discovery | UDP discovery broadcast listener |
51
+
52
+ ## Protocol status
53
+
54
+ The wire protocol is reverse engineered from the vendor Android, Java and Windows SDKs, cross-checked against the vendor's official protocol document. Every command of the document is implemented, including its module-level subset. No command has been verified against live hardware yet. The complete byte level reference, with every decoded payload layout and the unverified items, lives in [docs/protocol.md](docs/protocol.md). When a reader is available, `uv run python scripts/probe_chainway.py socket://192.168.99.200:8888` exercises every command and writes the responses to `captures/`.
55
+
56
+ While a continuous inventory runs, the reader answers no command except stop inventory. The client models this: other commands raise `ChainwayInventoryActiveError` until the scan ends.
57
+
58
+ ## Documentation
59
+
60
+ The full documentation is on [Read the Docs](https://chainway-serial.readthedocs.io/).
@@ -0,0 +1,141 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.12.21,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "chainway-serial"
7
+ version = "0.1.0"
8
+ description = "Asynchronous Python library for Chainway UR4 UHF RFID readers over serial and TCP"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.14"
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Framework :: AsyncIO",
16
+ "Intended Audience :: Developers",
17
+ "Programming Language :: Python :: 3.14",
18
+ "Topic :: System :: Hardware",
19
+ "Typing :: Typed",
20
+ ]
21
+ keywords = [
22
+ "chainway",
23
+ "ur4",
24
+ "uhf",
25
+ "rfid",
26
+ "epc",
27
+ "gen2",
28
+ "serial",
29
+ "tcp",
30
+ "serialx",
31
+ "asyncio",
32
+ "home-assistant",
33
+ ]
34
+ dependencies = ["serialx>=1.10"]
35
+
36
+ [[project.authors]]
37
+ name = "Daan Vervacke"
38
+ email = "daan.vervacke@proton.me"
39
+
40
+ [project.urls]
41
+ Homepage = "https://github.com/DaanVervacke/chainway-serial"
42
+ Repository = "https://github.com/DaanVervacke/chainway-serial"
43
+ Issues = "https://github.com/DaanVervacke/chainway-serial/issues"
44
+ Changelog = "https://github.com/DaanVervacke/chainway-serial/blob/main/CHANGELOG.md"
45
+ Documentation = "https://chainway-serial.readthedocs.io/"
46
+
47
+ [dependency-groups]
48
+ dev = [
49
+ "pytest>=9.0.3",
50
+ "pytest-asyncio>=1.3.0",
51
+ "mypy>=1.13",
52
+ "ruff>=0.16",
53
+ "coverage[toml]>=7.15.2",
54
+ ]
55
+ docs = [
56
+ "furo>=2025.12.19",
57
+ "sphinx>=9.1.0",
58
+ ]
59
+
60
+ [tool.uv]
61
+ required-version = ">=0.12.21,<0.13"
62
+
63
+ [tool.uv.build-backend]
64
+ source-include = ["LICENSE"]
65
+
66
+ [tool.ruff]
67
+ target-version = "py314"
68
+ line-length = 100
69
+ src = [
70
+ "src",
71
+ "tests",
72
+ ]
73
+ extend-exclude = [
74
+ ".claude",
75
+ ".agents",
76
+ ".codex",
77
+ ".continue",
78
+ ]
79
+
80
+ [tool.ruff.format]
81
+ docstring-code-format = true
82
+
83
+ [tool.ruff.lint]
84
+ select = ["ALL"]
85
+ ignore = [
86
+ "D",
87
+ "COM812",
88
+ "ISC001",
89
+ "ANN401",
90
+ "PLR0913",
91
+ "PLR0917",
92
+ "TC001",
93
+ "TC002",
94
+ "TC003",
95
+ "CPY001",
96
+ ]
97
+
98
+ [tool.ruff.lint.per-file-ignores]
99
+ "scripts/check.py" = [
100
+ "T201",
101
+ "S603",
102
+ ]
103
+ "scripts/probe_chainway.py" = [
104
+ "T201",
105
+ "S105",
106
+ "PLR2004",
107
+ ]
108
+ "docs/conf.py" = ["INP001"]
109
+ "tests/**" = [
110
+ "S101",
111
+ "S105",
112
+ "S106",
113
+ "SLF001",
114
+ "PLR2004",
115
+ "RUF059",
116
+ "FBT003",
117
+ ]
118
+
119
+ [tool.pytest.ini_options]
120
+ minversion = "9.0"
121
+ testpaths = ["tests"]
122
+ addopts = [
123
+ "-ra",
124
+ "--strict-markers",
125
+ "--strict-config",
126
+ ]
127
+ filterwarnings = ["error"]
128
+ asyncio_mode = "auto"
129
+
130
+ [tool.coverage.run]
131
+ branch = true
132
+ source = ["src"]
133
+
134
+ [tool.coverage.report]
135
+ show_missing = true
136
+ skip_covered = true
137
+ fail_under = 98
138
+
139
+ [tool.mypy]
140
+ python_version = "3.14"
141
+ strict = true
@@ -0,0 +1,119 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.12.21,<0.13"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "chainway-serial"
7
+ version = "0.1.0"
8
+ description = "Asynchronous Python library for Chainway UR4 UHF RFID readers over serial and TCP"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.14"
13
+ authors = [{ name = "Daan Vervacke", email = "daan.vervacke@proton.me" }]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Framework :: AsyncIO",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Topic :: System :: Hardware",
20
+ "Typing :: Typed",
21
+ ]
22
+ keywords = [
23
+ "chainway",
24
+ "ur4",
25
+ "uhf",
26
+ "rfid",
27
+ "epc",
28
+ "gen2",
29
+ "serial",
30
+ "tcp",
31
+ "serialx",
32
+ "asyncio",
33
+ "home-assistant",
34
+ ]
35
+ dependencies = ["serialx>=1.10"]
36
+
37
+ [dependency-groups]
38
+ dev = [
39
+ "pytest>=9.0.3",
40
+ "pytest-asyncio>=1.3.0",
41
+ "mypy>=1.13",
42
+ "ruff>=0.16",
43
+ "coverage[toml]>=7.15.2",
44
+ ]
45
+ docs = [
46
+ "furo>=2025.12.19",
47
+ "sphinx>=9.1.0",
48
+ ]
49
+
50
+ [project.urls]
51
+ Homepage = "https://github.com/DaanVervacke/chainway-serial"
52
+ Repository = "https://github.com/DaanVervacke/chainway-serial"
53
+ Issues = "https://github.com/DaanVervacke/chainway-serial/issues"
54
+ Changelog = "https://github.com/DaanVervacke/chainway-serial/blob/main/CHANGELOG.md"
55
+ Documentation = "https://chainway-serial.readthedocs.io/"
56
+
57
+ [tool.uv]
58
+ required-version = ">=0.12.21,<0.13"
59
+
60
+ [tool.uv.build-backend]
61
+ source-include = ["LICENSE"]
62
+
63
+ [tool.ruff]
64
+ target-version = "py314"
65
+ line-length = 100
66
+ src = ["src", "tests"]
67
+ extend-exclude = [".claude", ".agents", ".codex", ".continue"]
68
+
69
+ [tool.ruff.format]
70
+ docstring-code-format = true
71
+
72
+ [tool.ruff.lint]
73
+ select = ["ALL"]
74
+ ignore = [
75
+ "D",
76
+ "COM812",
77
+ "ISC001",
78
+ "ANN401",
79
+ "PLR0913",
80
+ "PLR0917",
81
+ "TC001",
82
+ "TC002",
83
+ "TC003",
84
+ "CPY001",
85
+ ]
86
+
87
+ [tool.ruff.lint.per-file-ignores]
88
+ "scripts/check.py" = ["T201", "S603"]
89
+ "scripts/probe_chainway.py" = ["T201", "S105", "PLR2004"]
90
+ "docs/conf.py" = ["INP001"]
91
+ "tests/**" = [
92
+ "S101",
93
+ "S105",
94
+ "S106",
95
+ "SLF001",
96
+ "PLR2004",
97
+ "RUF059",
98
+ "FBT003",
99
+ ]
100
+
101
+ [tool.pytest.ini_options]
102
+ minversion = "9.0"
103
+ testpaths = ["tests"]
104
+ addopts = ["-ra", "--strict-markers", "--strict-config"]
105
+ filterwarnings = ["error"]
106
+ asyncio_mode = "auto"
107
+
108
+ [tool.coverage.run]
109
+ branch = true
110
+ source = ["src"]
111
+
112
+ [tool.coverage.report]
113
+ show_missing = true
114
+ skip_covered = true
115
+ fail_under = 98
116
+
117
+ [tool.mypy]
118
+ python_version = "3.14"
119
+ strict = true
@@ -0,0 +1,91 @@
1
+ """Asynchronous Python library for Chainway UR4 UHF RFID readers.
2
+
3
+ The client speaks the reader wire protocol over any serialx URL: a
4
+ device path for RS-232, ``socket://host:8888`` for TCP, and the
5
+ rfc2217 or ESPHome proxies.
6
+ """
7
+
8
+ from importlib.metadata import PackageNotFoundError as _PackageNotFoundError
9
+ from importlib.metadata import version as _version
10
+
11
+ from .client import ChainwayClient, ConnectionLostCallback, TagCallback
12
+ from .discovery import discover_readers
13
+ from .exceptions import (
14
+ ChainwayConnectionError,
15
+ ChainwayError,
16
+ ChainwayInventoryActiveError,
17
+ ChainwayProtocolError,
18
+ ChainwayResponseError,
19
+ ChainwayTimeoutError,
20
+ )
21
+ from .models import (
22
+ AntennaPower,
23
+ AntennaState,
24
+ CollectedTags,
25
+ DiscoveredReader,
26
+ FirmwareVersion,
27
+ Gen2Parameters,
28
+ GpoState,
29
+ InventoryMode,
30
+ InventoryModeConfig,
31
+ LinkFrequency,
32
+ LockBank,
33
+ LockMode,
34
+ MemoryBank,
35
+ OutputRoute,
36
+ ProtocolType,
37
+ ReaderAddress,
38
+ Region,
39
+ ReturnLoss,
40
+ RfLink,
41
+ Tag,
42
+ TagFilter,
43
+ TriggerConfig,
44
+ TriggerInput,
45
+ WorkMode,
46
+ )
47
+ from .parsers import build_lock_code
48
+
49
+ try:
50
+ __version__ = _version("chainway-serial")
51
+ except _PackageNotFoundError:
52
+ __version__ = "0.0.0"
53
+
54
+ __all__ = [
55
+ "AntennaPower",
56
+ "AntennaState",
57
+ "ChainwayClient",
58
+ "ChainwayConnectionError",
59
+ "ChainwayError",
60
+ "ChainwayInventoryActiveError",
61
+ "ChainwayProtocolError",
62
+ "ChainwayResponseError",
63
+ "ChainwayTimeoutError",
64
+ "CollectedTags",
65
+ "ConnectionLostCallback",
66
+ "DiscoveredReader",
67
+ "FirmwareVersion",
68
+ "Gen2Parameters",
69
+ "GpoState",
70
+ "InventoryMode",
71
+ "InventoryModeConfig",
72
+ "LinkFrequency",
73
+ "LockBank",
74
+ "LockMode",
75
+ "MemoryBank",
76
+ "OutputRoute",
77
+ "ProtocolType",
78
+ "ReaderAddress",
79
+ "Region",
80
+ "ReturnLoss",
81
+ "RfLink",
82
+ "Tag",
83
+ "TagCallback",
84
+ "TagFilter",
85
+ "TriggerConfig",
86
+ "TriggerInput",
87
+ "WorkMode",
88
+ "__version__",
89
+ "build_lock_code",
90
+ "discover_readers",
91
+ ]