ok-serial 0.1__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.
- ok_serial-0.1/PKG-INFO +218 -0
- ok_serial-0.1/README.md +202 -0
- ok_serial-0.1/ok_serial/__init__.py +35 -0
- ok_serial-0.1/ok_serial/_connection.py +365 -0
- ok_serial-0.1/ok_serial/_exceptions.py +35 -0
- ok_serial-0.1/ok_serial/_locking.py +151 -0
- ok_serial-0.1/ok_serial/_scanning.py +159 -0
- ok_serial-0.1/ok_serial/_timeout_math.py +20 -0
- ok_serial-0.1/ok_serial/_tracker.py +113 -0
- ok_serial-0.1/ok_serial/ok_scan_serial_cli.py +99 -0
- ok_serial-0.1/pyproject.toml +53 -0
ok_serial-0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ok-serial
|
|
3
|
+
Version: 0.1
|
|
4
|
+
Summary: Serial port library (PySerial wrapper) with more features
|
|
5
|
+
Author: Dan Egnor
|
|
6
|
+
Author-email: Dan Egnor <egnor@ofb.net>
|
|
7
|
+
Requires-Dist: beartype>=0.22.9
|
|
8
|
+
Requires-Dist: natsort>=8.4.0
|
|
9
|
+
Requires-Dist: ok-logging-setup>=0.11
|
|
10
|
+
Requires-Dist: pyserial>=3.5
|
|
11
|
+
Requires-Dist: types-pyserial>=3.5.0.20251001
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Project-URL: Homepage, https://github.com/egnor/ok-py-serial#readme
|
|
14
|
+
Project-URL: Repository, https://github.com/egnor/ok-py-serial.git
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# ok-serial for Python ๐ใกใใกใใก๐
|
|
18
|
+
|
|
19
|
+
Python serial I/O library [based on PySerial](https://www.pyserial.com/) with
|
|
20
|
+
improved discovery and interface semantics.
|
|
21
|
+
|
|
22
|
+
Think twice before using this library! Consider something more established:
|
|
23
|
+
|
|
24
|
+
- [good old PySerial](https://www.pyserial.com/) - it is _very_ well established
|
|
25
|
+
- [pyserial-asyncio](https://github.com/pyserial/pyserial-asyncio) - official
|
|
26
|
+
and "proper" [asyncio](https://docs.python.org/3/library/asyncio.html)
|
|
27
|
+
support for PySerial
|
|
28
|
+
- [pyserial-asyncio-fast](https://github.com/home-assistant-libs/pyserial-asyncio-fast)
|
|
29
|
+
\- a fork of pyserial-asyncio designed for more efficient writes
|
|
30
|
+
- [aioserial](https://github.com/mrjohannchang/aioserial.py) - alternative
|
|
31
|
+
asyncio wrapper designed for ease of use
|
|
32
|
+
|
|
33
|
+
## Purpose
|
|
34
|
+
|
|
35
|
+
Since 2001, [PySerial](https://www.pyserial.com/) has been the
|
|
36
|
+
workhorse [serial port](https://en.wikipedia.org/wiki/Serial_port)
|
|
37
|
+
([UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter))
|
|
38
|
+
library for Python. It runs on most Python platforms and abstracts
|
|
39
|
+
lots of gnarly system details. However, some problems keep coming up:
|
|
40
|
+
|
|
41
|
+
- Most serial ports are USB, and USB serial ports get assigned cryptic
|
|
42
|
+
temporary names like `/dev/ttyACM3` or `COM4`. Using
|
|
43
|
+
[`serial.tools.list_ports.grep(...)`](https://pythonhosted.org/pyserial/tools.html#serial.tools.list_ports.grep)
|
|
44
|
+
is a clumsy multi step process; linux allows
|
|
45
|
+
[udev rules](https://dev.to/enbis/how-udev-rules-can-help-us-to-recognize-a-usb-to-serial-device-over-dev-tty-interface-pbk)
|
|
46
|
+
but they're not exactly user friendly.
|
|
47
|
+
|
|
48
|
+
- Nonblocking or concurrent I/O with PySerial is perilous and often
|
|
49
|
+
[broken](https://github.com/pyserial/pyserial/issues/281)
|
|
50
|
+
[entirely](https://github.com/pyserial/pyserial/issues/280).
|
|
51
|
+
|
|
52
|
+
- Buffer sizes are finite and unspecified; overruns cause lost data
|
|
53
|
+
and/or blocking.
|
|
54
|
+
|
|
55
|
+
- Port locking is off by default in PySerial; even if enabled, it only
|
|
56
|
+
uses one advisory locking method. Bad things happen if multiple programs
|
|
57
|
+
try to use the same port.
|
|
58
|
+
|
|
59
|
+
The `ok-serial` library uses PySerial internally but has its own consistent
|
|
60
|
+
interface to fix these problems and be generally smoove:
|
|
61
|
+
|
|
62
|
+
- Ports are referenced by
|
|
63
|
+
[string expressions](#identifying-ports) that can match attributes
|
|
64
|
+
with wildcard support, eg. `desc:Arduino*` or `2e43:0226` or `*RP2040*`.
|
|
65
|
+
(You can also specify exact device path if desired.)
|
|
66
|
+
|
|
67
|
+
- I/O operations are thread safe and can be blocking, non-blocking,
|
|
68
|
+
timeout, or async. All blocking operations can be interrupted.
|
|
69
|
+
Semantics are well described, including concurrent access, partial
|
|
70
|
+
reads/writes, errors, and other edge cases.
|
|
71
|
+
|
|
72
|
+
- I/O buffers are unlimited except for system memory; writes
|
|
73
|
+
never block. (You can use a blocking drain operation to wait for
|
|
74
|
+
output completion if desired.)
|
|
75
|
+
|
|
76
|
+
- Includes [multiple port locking modes](#sharing-modes) with exclusive locking
|
|
77
|
+
as the default. Employs _all_ of
|
|
78
|
+
[`/var/lock/LCK..*` files](https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch05s09.html),
|
|
79
|
+
[`flock(...)`](https://linux.die.net/man/2/flock) (like PySerial),
|
|
80
|
+
and [`TIOCEXCL`](https://man7.org/linux/man-pages/man2/TIOCEXCL.2const.html)
|
|
81
|
+
(as available) to avoid contention.
|
|
82
|
+
|
|
83
|
+
- Includes a `SerialTracker` helper to wait for a device of interest to
|
|
84
|
+
appear, rescanning as needed after disconnection, to handle devices
|
|
85
|
+
that might get plugged and unplugged.
|
|
86
|
+
|
|
87
|
+
## Installation
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pip install ok-serial
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
(or `uv add ok-serial`, etc.)
|
|
94
|
+
|
|
95
|
+
## Identifying ports
|
|
96
|
+
|
|
97
|
+
Device names like `/dev/ttyUSB3` or `COM4` aren't very useful for USB
|
|
98
|
+
serial ports, so `ok-serial` uses **port match expressions** which
|
|
99
|
+
are strings that identify ports of interest by attributes such as the
|
|
100
|
+
device manufacturer (eg. `Adafruit`), product name (eg.
|
|
101
|
+
`CP2102 USB to UART Bridge Controller`), USB vendor/product ID (eg.
|
|
102
|
+
`239a:812d`), serial number, or other properties.
|
|
103
|
+
|
|
104
|
+
To see port attributes, install `ok-serial` and run
|
|
105
|
+
`ok_scan_serial --verbose` to list available ports like this:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
Serial port: /dev/ttyACM3
|
|
109
|
+
device: '/dev/ttyACM3'
|
|
110
|
+
name: 'ttyACM3'
|
|
111
|
+
description: 'Feather RP2040 RFM - Pico Serial'
|
|
112
|
+
hwid: 'USB VID:PID=239A:812D SER=DF62585783553434 LOCATION=3-2.1:1.0'
|
|
113
|
+
vid: '9114'
|
|
114
|
+
pid: '33069'
|
|
115
|
+
serial_number: 'DF62585783553434'
|
|
116
|
+
location: '3-2.1:1.0'
|
|
117
|
+
manufacturer: 'Adafruit'
|
|
118
|
+
product: 'Feather RP2040 RFM'
|
|
119
|
+
interface: 'Pico Serial'
|
|
120
|
+
usb_device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1'
|
|
121
|
+
device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
122
|
+
subsystem: 'usb'
|
|
123
|
+
usb_interface_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Attribute names and value formats are inherited from PySerial and
|
|
127
|
+
the underlying OS and can vary, but
|
|
128
|
+
`device`, `name`, `description`, `hwid`, and (for USB) `vid`, `pid`,
|
|
129
|
+
`serial_number`, `location`, `manufacturer`, `product` and `interface`
|
|
130
|
+
are semi-standardized.
|
|
131
|
+
|
|
132
|
+
Match expressions can be a simple value, selecting any port with a
|
|
133
|
+
matching value (case-insensitive whole-string match):
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
Pico Serial
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Match values can include `*` and `?` wildcards:
|
|
140
|
+
|
|
141
|
+
```text
|
|
142
|
+
*RP2040*
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Expressions can include a field selector (prefix abbreviation is OK):
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
subsys:usb
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Values containing colons, quotes, or special characters
|
|
152
|
+
should be quoted using Python/C/JS string escaping:
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
location:"3-2.1:1.0"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Multiple constraints can be combined; all must match:
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
manufacturer:Adafruit serial:DF625*
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
To experiment, pass a match expression to `ok_scan_serial` on the
|
|
165
|
+
command line; set `$OK_LOGGING_LEVEL=debug` to see the parse result:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
% OK_LOGGING_LEVEL=debug ok_scan_serial -v 'manufacturer:Adafruit serial:DF625*'
|
|
169
|
+
๐ธ ok_serial.scanning: Parsed 'manufacturer:Adafruit serial:DF625*':
|
|
170
|
+
manufacturer: /(?s:Adafruit)\Z/
|
|
171
|
+
serial: /(?s:DF625.*)\Z/
|
|
172
|
+
๐ธ ok_serial.scanning: Found 36 ports
|
|
173
|
+
36 serial ports found, 1 matches 'manufacturer:Adafruit serial:DF625*'
|
|
174
|
+
Serial port: /dev/ttyACM3
|
|
175
|
+
device: '/dev/ttyACM3'
|
|
176
|
+
name: 'ttyACM3'
|
|
177
|
+
description: 'Feather RP2040 RFM - Pico Serial'
|
|
178
|
+
hwid: 'USB VID:PID=239A:812D SER=DF62585783553434 LOCATION=3-2.1:1.0'
|
|
179
|
+
vid: '9114'
|
|
180
|
+
pid: '33069'
|
|
181
|
+
serial_number: 'DF62585783553434'
|
|
182
|
+
location: '3-2.1:1.0'
|
|
183
|
+
manufacturer: 'Adafruit'
|
|
184
|
+
product: 'Feather RP2040 RFM'
|
|
185
|
+
interface: 'Pico Serial'
|
|
186
|
+
usb_device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1'
|
|
187
|
+
device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
188
|
+
subsystem: 'usb'
|
|
189
|
+
usb_interface_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Sharing modes
|
|
193
|
+
|
|
194
|
+
When opening a port, `ok-serial` offers a choice of four sharing modes:
|
|
195
|
+
|
|
196
|
+
- `oblivious` - no locking is done and advisory locks are ignored. If
|
|
197
|
+
multiple programs open the port, they will all send and receive data
|
|
198
|
+
to the same device. This mode is not recommended.
|
|
199
|
+
|
|
200
|
+
- `polite` - locking is checked at open, and if the port is in use the
|
|
201
|
+
open fails. Once opened, no locks are held except for a shared lock
|
|
202
|
+
to discourage other `polite` users from opening the port. If a
|
|
203
|
+
less polite program opens the port later there will be conflict.
|
|
204
|
+
(In the future, this mode will attempt to notice such conflicts
|
|
205
|
+
and close out the port, deferring to the less-polite program.)
|
|
206
|
+
|
|
207
|
+
- `exclusive` (the default mode) - locking is checked at open, and if the
|
|
208
|
+
port is in use the open fails. Once opened, several means of locking
|
|
209
|
+
are employed to prevent or discourage others from opening the port.
|
|
210
|
+
|
|
211
|
+
- `stomp` (use with care!) - locking is checked at open, and if the port
|
|
212
|
+
is in use, _the program using the port is killed_ if permissions
|
|
213
|
+
allow. The port is opened regardless of any other users and all
|
|
214
|
+
available locks are taken.
|
|
215
|
+
|
|
216
|
+
The library's ability to implement these modes can be limited by
|
|
217
|
+
operating system capabilities, process permissions, and the variously
|
|
218
|
+
questionable historical conventions for port usage coordination.
|
ok_serial-0.1/README.md
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# ok-serial for Python ๐ใกใใกใใก๐
|
|
2
|
+
|
|
3
|
+
Python serial I/O library [based on PySerial](https://www.pyserial.com/) with
|
|
4
|
+
improved discovery and interface semantics.
|
|
5
|
+
|
|
6
|
+
Think twice before using this library! Consider something more established:
|
|
7
|
+
|
|
8
|
+
- [good old PySerial](https://www.pyserial.com/) - it is _very_ well established
|
|
9
|
+
- [pyserial-asyncio](https://github.com/pyserial/pyserial-asyncio) - official
|
|
10
|
+
and "proper" [asyncio](https://docs.python.org/3/library/asyncio.html)
|
|
11
|
+
support for PySerial
|
|
12
|
+
- [pyserial-asyncio-fast](https://github.com/home-assistant-libs/pyserial-asyncio-fast)
|
|
13
|
+
\- a fork of pyserial-asyncio designed for more efficient writes
|
|
14
|
+
- [aioserial](https://github.com/mrjohannchang/aioserial.py) - alternative
|
|
15
|
+
asyncio wrapper designed for ease of use
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
|
|
19
|
+
Since 2001, [PySerial](https://www.pyserial.com/) has been the
|
|
20
|
+
workhorse [serial port](https://en.wikipedia.org/wiki/Serial_port)
|
|
21
|
+
([UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter))
|
|
22
|
+
library for Python. It runs on most Python platforms and abstracts
|
|
23
|
+
lots of gnarly system details. However, some problems keep coming up:
|
|
24
|
+
|
|
25
|
+
- Most serial ports are USB, and USB serial ports get assigned cryptic
|
|
26
|
+
temporary names like `/dev/ttyACM3` or `COM4`. Using
|
|
27
|
+
[`serial.tools.list_ports.grep(...)`](https://pythonhosted.org/pyserial/tools.html#serial.tools.list_ports.grep)
|
|
28
|
+
is a clumsy multi step process; linux allows
|
|
29
|
+
[udev rules](https://dev.to/enbis/how-udev-rules-can-help-us-to-recognize-a-usb-to-serial-device-over-dev-tty-interface-pbk)
|
|
30
|
+
but they're not exactly user friendly.
|
|
31
|
+
|
|
32
|
+
- Nonblocking or concurrent I/O with PySerial is perilous and often
|
|
33
|
+
[broken](https://github.com/pyserial/pyserial/issues/281)
|
|
34
|
+
[entirely](https://github.com/pyserial/pyserial/issues/280).
|
|
35
|
+
|
|
36
|
+
- Buffer sizes are finite and unspecified; overruns cause lost data
|
|
37
|
+
and/or blocking.
|
|
38
|
+
|
|
39
|
+
- Port locking is off by default in PySerial; even if enabled, it only
|
|
40
|
+
uses one advisory locking method. Bad things happen if multiple programs
|
|
41
|
+
try to use the same port.
|
|
42
|
+
|
|
43
|
+
The `ok-serial` library uses PySerial internally but has its own consistent
|
|
44
|
+
interface to fix these problems and be generally smoove:
|
|
45
|
+
|
|
46
|
+
- Ports are referenced by
|
|
47
|
+
[string expressions](#identifying-ports) that can match attributes
|
|
48
|
+
with wildcard support, eg. `desc:Arduino*` or `2e43:0226` or `*RP2040*`.
|
|
49
|
+
(You can also specify exact device path if desired.)
|
|
50
|
+
|
|
51
|
+
- I/O operations are thread safe and can be blocking, non-blocking,
|
|
52
|
+
timeout, or async. All blocking operations can be interrupted.
|
|
53
|
+
Semantics are well described, including concurrent access, partial
|
|
54
|
+
reads/writes, errors, and other edge cases.
|
|
55
|
+
|
|
56
|
+
- I/O buffers are unlimited except for system memory; writes
|
|
57
|
+
never block. (You can use a blocking drain operation to wait for
|
|
58
|
+
output completion if desired.)
|
|
59
|
+
|
|
60
|
+
- Includes [multiple port locking modes](#sharing-modes) with exclusive locking
|
|
61
|
+
as the default. Employs _all_ of
|
|
62
|
+
[`/var/lock/LCK..*` files](https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch05s09.html),
|
|
63
|
+
[`flock(...)`](https://linux.die.net/man/2/flock) (like PySerial),
|
|
64
|
+
and [`TIOCEXCL`](https://man7.org/linux/man-pages/man2/TIOCEXCL.2const.html)
|
|
65
|
+
(as available) to avoid contention.
|
|
66
|
+
|
|
67
|
+
- Includes a `SerialTracker` helper to wait for a device of interest to
|
|
68
|
+
appear, rescanning as needed after disconnection, to handle devices
|
|
69
|
+
that might get plugged and unplugged.
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install ok-serial
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
(or `uv add ok-serial`, etc.)
|
|
78
|
+
|
|
79
|
+
## Identifying ports
|
|
80
|
+
|
|
81
|
+
Device names like `/dev/ttyUSB3` or `COM4` aren't very useful for USB
|
|
82
|
+
serial ports, so `ok-serial` uses **port match expressions** which
|
|
83
|
+
are strings that identify ports of interest by attributes such as the
|
|
84
|
+
device manufacturer (eg. `Adafruit`), product name (eg.
|
|
85
|
+
`CP2102 USB to UART Bridge Controller`), USB vendor/product ID (eg.
|
|
86
|
+
`239a:812d`), serial number, or other properties.
|
|
87
|
+
|
|
88
|
+
To see port attributes, install `ok-serial` and run
|
|
89
|
+
`ok_scan_serial --verbose` to list available ports like this:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
Serial port: /dev/ttyACM3
|
|
93
|
+
device: '/dev/ttyACM3'
|
|
94
|
+
name: 'ttyACM3'
|
|
95
|
+
description: 'Feather RP2040 RFM - Pico Serial'
|
|
96
|
+
hwid: 'USB VID:PID=239A:812D SER=DF62585783553434 LOCATION=3-2.1:1.0'
|
|
97
|
+
vid: '9114'
|
|
98
|
+
pid: '33069'
|
|
99
|
+
serial_number: 'DF62585783553434'
|
|
100
|
+
location: '3-2.1:1.0'
|
|
101
|
+
manufacturer: 'Adafruit'
|
|
102
|
+
product: 'Feather RP2040 RFM'
|
|
103
|
+
interface: 'Pico Serial'
|
|
104
|
+
usb_device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1'
|
|
105
|
+
device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
106
|
+
subsystem: 'usb'
|
|
107
|
+
usb_interface_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Attribute names and value formats are inherited from PySerial and
|
|
111
|
+
the underlying OS and can vary, but
|
|
112
|
+
`device`, `name`, `description`, `hwid`, and (for USB) `vid`, `pid`,
|
|
113
|
+
`serial_number`, `location`, `manufacturer`, `product` and `interface`
|
|
114
|
+
are semi-standardized.
|
|
115
|
+
|
|
116
|
+
Match expressions can be a simple value, selecting any port with a
|
|
117
|
+
matching value (case-insensitive whole-string match):
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
Pico Serial
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Match values can include `*` and `?` wildcards:
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
*RP2040*
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Expressions can include a field selector (prefix abbreviation is OK):
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
subsys:usb
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Values containing colons, quotes, or special characters
|
|
136
|
+
should be quoted using Python/C/JS string escaping:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
location:"3-2.1:1.0"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Multiple constraints can be combined; all must match:
|
|
143
|
+
|
|
144
|
+
```text
|
|
145
|
+
manufacturer:Adafruit serial:DF625*
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
To experiment, pass a match expression to `ok_scan_serial` on the
|
|
149
|
+
command line; set `$OK_LOGGING_LEVEL=debug` to see the parse result:
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
% OK_LOGGING_LEVEL=debug ok_scan_serial -v 'manufacturer:Adafruit serial:DF625*'
|
|
153
|
+
๐ธ ok_serial.scanning: Parsed 'manufacturer:Adafruit serial:DF625*':
|
|
154
|
+
manufacturer: /(?s:Adafruit)\Z/
|
|
155
|
+
serial: /(?s:DF625.*)\Z/
|
|
156
|
+
๐ธ ok_serial.scanning: Found 36 ports
|
|
157
|
+
36 serial ports found, 1 matches 'manufacturer:Adafruit serial:DF625*'
|
|
158
|
+
Serial port: /dev/ttyACM3
|
|
159
|
+
device: '/dev/ttyACM3'
|
|
160
|
+
name: 'ttyACM3'
|
|
161
|
+
description: 'Feather RP2040 RFM - Pico Serial'
|
|
162
|
+
hwid: 'USB VID:PID=239A:812D SER=DF62585783553434 LOCATION=3-2.1:1.0'
|
|
163
|
+
vid: '9114'
|
|
164
|
+
pid: '33069'
|
|
165
|
+
serial_number: 'DF62585783553434'
|
|
166
|
+
location: '3-2.1:1.0'
|
|
167
|
+
manufacturer: 'Adafruit'
|
|
168
|
+
product: 'Feather RP2040 RFM'
|
|
169
|
+
interface: 'Pico Serial'
|
|
170
|
+
usb_device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1'
|
|
171
|
+
device_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
172
|
+
subsystem: 'usb'
|
|
173
|
+
usb_interface_path: '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2.1/3-2.1:1.0'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Sharing modes
|
|
177
|
+
|
|
178
|
+
When opening a port, `ok-serial` offers a choice of four sharing modes:
|
|
179
|
+
|
|
180
|
+
- `oblivious` - no locking is done and advisory locks are ignored. If
|
|
181
|
+
multiple programs open the port, they will all send and receive data
|
|
182
|
+
to the same device. This mode is not recommended.
|
|
183
|
+
|
|
184
|
+
- `polite` - locking is checked at open, and if the port is in use the
|
|
185
|
+
open fails. Once opened, no locks are held except for a shared lock
|
|
186
|
+
to discourage other `polite` users from opening the port. If a
|
|
187
|
+
less polite program opens the port later there will be conflict.
|
|
188
|
+
(In the future, this mode will attempt to notice such conflicts
|
|
189
|
+
and close out the port, deferring to the less-polite program.)
|
|
190
|
+
|
|
191
|
+
- `exclusive` (the default mode) - locking is checked at open, and if the
|
|
192
|
+
port is in use the open fails. Once opened, several means of locking
|
|
193
|
+
are employed to prevent or discourage others from opening the port.
|
|
194
|
+
|
|
195
|
+
- `stomp` (use with care!) - locking is checked at open, and if the port
|
|
196
|
+
is in use, _the program using the port is killed_ if permissions
|
|
197
|
+
allow. The port is opened regardless of any other users and all
|
|
198
|
+
available locks are taken.
|
|
199
|
+
|
|
200
|
+
The library's ability to implement these modes can be limited by
|
|
201
|
+
operating system capabilities, process permissions, and the variously
|
|
202
|
+
questionable historical conventions for port usage coordination.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Serial port library (PySerial wrapper) with improved discovery,
|
|
3
|
+
port sharing semantics, and interface.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from ok_serial._connection import (
|
|
7
|
+
SerialConnection,
|
|
8
|
+
SerialOptions,
|
|
9
|
+
SerialSignals,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from ok_serial._exceptions import (
|
|
13
|
+
OkSerialException,
|
|
14
|
+
SerialIoClosed,
|
|
15
|
+
SerialIoException,
|
|
16
|
+
SerialMatcherInvalid,
|
|
17
|
+
SerialOpenBusy,
|
|
18
|
+
SerialOpenException,
|
|
19
|
+
SerialScanException,
|
|
20
|
+
)
|
|
21
|
+
from ok_serial._locking import SerialSharingType
|
|
22
|
+
|
|
23
|
+
from ok_serial._scanning import (
|
|
24
|
+
SerialPort,
|
|
25
|
+
SerialPortMatcher,
|
|
26
|
+
scan_serial_ports,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
from ok_serial._tracker import SerialTracker, TrackerOptions
|
|
30
|
+
|
|
31
|
+
from beartype.claw import beartype_this_package as _beartype_me
|
|
32
|
+
|
|
33
|
+
_beartype_me()
|
|
34
|
+
|
|
35
|
+
__all__ = [n for n in dir() if not n.startswith("_")]
|