Skip to content

Commit 1b37a22

Browse files
committed
rework package structure to prepare for distribution
1 parent ed8ec3e commit 1b37a22

11 files changed

+336
-397
lines changed

README.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Python PLIN library
2-
The plin module provides a Python interface for interacting with PEAK devices such as the PCAN-USB Pro and PLIN-USB on Linux using the chardev API provided by the PEAK LIN Linux Beta. The PEAK Linux beta driver is required to use this library and is available [here](https://forum.peak-system.com/viewtopic.php?t=5875).
2+
This library provides a Python interface for interacting with PEAK devices such as the PCAN-USB Pro and PLIN-USB on Linux using the chardev API provided by the PEAK LIN Linux Beta. The PEAK Linux beta driver is required to use this library and is available [here](https://forum.peak-system.com/viewtopic.php?t=5875).
3+
4+
## Installation
5+
The `plin-linux` package is available on [PyPI](https://pypi.org/project/plin-linux/) and can be directly installed with `pip install plin-linux`.
36

47
## Examples
58
Runnable examples are located in the `examples/` directory.
@@ -76,7 +79,9 @@ while True:
7679
```
7780

7881
## Unit Tests
79-
Unit tests are located in the `unit_tests/` directory and require a PEAK LIN device connected to run.
82+
* Unit tests are located in the `unit_tests/` directory.
83+
* Requires a PEAK LIN device connected to run.
84+
* Can be run with `pytest`.
8085

8186
## License
8287

examples/master_test.py examples/master.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from plin.enums import (PLINFrameChecksumType, PLINFrameDirection,
66
PLINFrameFlag, PLINMode)
7-
from plin.plin import PLIN
7+
from plin.device import PLIN
88

99
pp = pprint.PrettyPrinter(indent=4)
1010

examples/slave_test.py examples/slave.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import sys
33

44
from plin.enums import PLINFrameChecksumType, PLINFrameDirection, PLINMode
5-
from plin.plin import PLIN
5+
from plin.device import PLIN
66

77

88
def main():

plin/plin.py plin/device.py

+1-293
Original file line numberDiff line numberDiff line change
@@ -7,299 +7,7 @@
77
from ioctl_opt import IO, IOW, IOWR
88

99
from plin.enums import *
10-
11-
PLIN_USB_FILTER_LEN = 8
12-
PLIN_DAT_LEN = 8
13-
PLIN_EMPTY_DATA = b'\xff' * PLIN_DAT_LEN
14-
15-
16-
class PLINMessage(Structure):
17-
'''
18-
Class representing a LIN message.
19-
'''
20-
buffer_length = 32
21-
_fields_ = [
22-
("type", c_uint16),
23-
("flags", c_uint16),
24-
("id", c_uint8),
25-
("len", c_uint8),
26-
("dir", c_uint8),
27-
("cs_type", c_uint8),
28-
("ts_us", c_uint64),
29-
("data", c_uint8 * PLIN_DAT_LEN),
30-
("reserved", c_uint8 * 8)
31-
]
32-
33-
def __setattr__(self, name: str, value: Any) -> None:
34-
if name == "data":
35-
buf = (c_uint8 * PLIN_DAT_LEN)(*value)
36-
return super().__setattr__(name, buf)
37-
else:
38-
return super().__setattr__(name, value)
39-
40-
def __repr__(self) -> str:
41-
return str(self._asdict())
42-
43-
def _asdict(self) -> dict:
44-
result = {field[0]: getattr(self, field[0])
45-
for field in self._fields_[:-2]}
46-
result["type"] = PLINMessageType(self.type)
47-
result["dir"] = PLINFrameDirection(self.dir)
48-
result["flags"] = PLINFrameFlag(self.flags)
49-
result["cs_type"] = PLINFrameChecksumType(self.cs_type)
50-
result["data"] = bytearray(self.data)
51-
return result
52-
53-
54-
class PLINUSBInitHardware(Structure):
55-
_fields_ = [
56-
("baudrate", c_uint16),
57-
("mode", c_uint8),
58-
("unused", c_uint8)
59-
]
60-
61-
62-
class PLINUSBFrameEntry(Structure):
63-
_fields_ = [
64-
("id", c_uint8),
65-
("len", c_uint8),
66-
("direction", c_uint8),
67-
("checksum", c_uint8),
68-
("flags", c_uint16),
69-
("unused", c_uint16),
70-
("d", c_uint8 * PLIN_DAT_LEN)
71-
]
72-
73-
def __setattr__(self, name: str, value: Any) -> None:
74-
if name == "d":
75-
buf = (c_uint8 * PLIN_DAT_LEN)(*value)
76-
return super().__setattr__(name, buf)
77-
else:
78-
return super().__setattr__(name, value)
79-
80-
def __repr__(self) -> str:
81-
return str(self._asdict())
82-
83-
def _asdict(self) -> dict:
84-
result = {field: getattr(self, field)
85-
for field, _ in self._fields_}
86-
result["direction"] = PLINFrameDirection(self.direction)
87-
result["checksum"] = PLINFrameChecksumType(self.checksum)
88-
result["flags"] = PLINFrameFlag(self.flags)
89-
result["d"] = bytearray(self.d)
90-
del result["unused"]
91-
return result
92-
93-
94-
class PLINUSBAutoBaud(Structure):
95-
_fields_ = [
96-
("timeout", c_uint16),
97-
("err", c_uint8),
98-
("unused", c_uint8)
99-
]
100-
101-
102-
class PLINUSBGetBaudrate(Structure):
103-
_fields_ = [
104-
("baudrate", c_uint16),
105-
("unused", c_uint16)
106-
]
107-
108-
109-
class PLINUSBIDFilter(Structure):
110-
_fields_ = [
111-
("id_mask", c_uint8 * PLIN_USB_FILTER_LEN)
112-
]
113-
114-
115-
class PLINUSBGetMode(Structure):
116-
_fields_ = [
117-
("mode", c_uint8),
118-
("unused", c_uint8 * 3)
119-
]
120-
121-
122-
class PLINUSBIDString(Structure):
123-
_fields_ = [
124-
("str", c_char * 48)
125-
]
126-
127-
128-
class PLINUSBFirmwareVersion(Structure):
129-
_fields_ = [
130-
("major", c_uint8),
131-
("minor", c_uint8),
132-
("sub", c_uint16)
133-
]
134-
135-
136-
class PLINUSBKeepAlive(Structure):
137-
_fields_ = [
138-
("err", c_uint8),
139-
("id", c_uint8),
140-
("period_ms", c_uint16)
141-
]
142-
143-
144-
class PLINUSBAddScheduleSlot(Structure):
145-
_fields_ = [
146-
("schedule", c_uint8),
147-
("err", c_uint8),
148-
("unused", c_uint16),
149-
("type", c_uint8), # PLIN_USB_SLOT_xxx
150-
("count_resolve", c_uint8),
151-
("delay", c_uint16),
152-
("id", c_uint8 * PLINUSBSlotNumber.MAX),
153-
("handle", c_uint32)
154-
]
155-
156-
157-
class PLINUSBDeleteSchedule(Structure):
158-
_fields_ = [
159-
("schedule", c_uint8),
160-
("err", c_uint8),
161-
("unused", c_uint16),
162-
]
163-
164-
165-
class PLINUSBGetSlotCount(Structure):
166-
_fields_ = [
167-
("schedule", c_uint8),
168-
("unused", c_uint8),
169-
("count", c_uint16)
170-
]
171-
172-
173-
class PLINUSBGetScheduleSlot(Structure):
174-
_fields_ = [
175-
("schedule", c_uint8), # schedule from which the slot is returned
176-
("slot_idx", c_uint8), # slot index returned
177-
("err", c_uint8), # if 1, no schedule present
178-
("unused", c_uint8),
179-
("type", c_uint8), # PLIN_USB_SLOT_xxx
180-
("count_resolve", c_uint8),
181-
("delay", c_uint16),
182-
("id", c_uint8 * PLINUSBSlotNumber.MAX),
183-
("handle", c_uint32)
184-
]
185-
186-
def __repr__(self) -> str:
187-
return str(self._asdict())
188-
189-
def _asdict(self) -> dict:
190-
result = {field: getattr(self, field)
191-
for field, _ in self._fields_}
192-
result["type"] = PLINUSBSlotType(self.type)
193-
result["id"] = list(self.id)
194-
del result["unused"]
195-
return result
196-
197-
198-
class PLINUSBSetScheduleBreakpoint(Structure):
199-
_fields_ = [
200-
("brkpt", c_uint8), # either 0 or 1
201-
("unused", c_uint8 * 3),
202-
("handle", c_uint32) # slot handle returned
203-
]
204-
205-
206-
class PLINUSBStartSchedule(Structure):
207-
_fields_ = [
208-
("schedule", c_uint8),
209-
("err", c_uint8),
210-
("unused", c_uint16),
211-
]
212-
213-
214-
class PLINUSBResumeSchedule(Structure):
215-
_fields_ = [
216-
("err", c_uint8), # if 1, not master / no schedule started
217-
("unused", c_uint8 * 3),
218-
]
219-
220-
221-
class PLINUSBSuspendSchedule(Structure):
222-
_fields_ = [
223-
("err", c_uint8),
224-
("schedule", c_uint8), # suspended schedule index [0..7]
225-
("unused", c_uint8 * 2),
226-
("handle", c_uint32)
227-
]
228-
229-
230-
class PLINUSBGetStatus(Structure):
231-
_fields_ = [
232-
("mode", c_uint8),
233-
("tx_qfree", c_uint8),
234-
("schd_poolfree", c_uint16),
235-
("baudrate", c_uint16),
236-
("usb_rx_ovr", c_uint16), # USB data overrun counter
237-
("usb_filter", c_uint64),
238-
("bus_state", c_uint8),
239-
("unused", c_uint8 * 3)
240-
]
241-
242-
def __repr__(self) -> str:
243-
return str(self._asdict())
244-
245-
def _asdict(self) -> dict:
246-
result = {field: getattr(self, field)
247-
for field, _ in self._fields_}
248-
result["mode"] = PLINMode(self.mode)
249-
if self.usb_filter == 0:
250-
result["usb_filter"] = bytearray([0] * PLIN_USB_FILTER_LEN)
251-
else:
252-
result["usb_filter"] = bytearray.fromhex(
253-
f"{self.usb_filter:x}").ljust(PLIN_USB_FILTER_LEN, b'\x00')
254-
result["bus_state"] = PLINBusState(self.bus_state)
255-
del result["unused"]
256-
return result
257-
258-
259-
class PLINUSBUpdateData(Structure):
260-
_fields_ = [
261-
("id", c_uint8), # frame ID to update [0..63]
262-
("len", c_uint8), # count of data bytes to update [1..8]
263-
("idx", c_uint8), # data offset [0..7]
264-
("unused", c_uint8),
265-
("d", c_uint8 * PLIN_DAT_LEN) # new data bytes
266-
]
267-
268-
def __setattr__(self, name: str, value: Any) -> None:
269-
if name == "d":
270-
buf = (c_uint8 * PLIN_DAT_LEN)(*value)
271-
return super().__setattr__(name, buf)
272-
else:
273-
return super().__setattr__(name, value)
274-
275-
def __repr__(self) -> str:
276-
return str(self._asdict())
277-
278-
def _asdict(self) -> dict:
279-
result = {field: getattr(self, field)
280-
for field, _ in self._fields_}
281-
result["d"] = bytearray(result["d"])
282-
del result["unused"]
283-
return result
284-
285-
286-
PLIN_USB_RSP_REMAP_ID_LEN = (PLINFrameID.MAX - PLINFrameID.MIN + 1)
287-
288-
289-
class PLINUSBResponseRemap(Structure):
290-
_fields_ = [
291-
("set_get", c_uint8),
292-
("unused", c_uint8 * 3),
293-
("id", c_uint8 * PLIN_USB_RSP_REMAP_ID_LEN)
294-
]
295-
296-
297-
class PLINUSBLEDState(Structure):
298-
_fields_ = [
299-
("on_off", c_uint8), # PLIN_USB_LEDS_xxx
300-
("unused", c_uint8 * 3)
301-
]
302-
10+
from plin.structs import *
30311

30412
PLIOHWINIT = IOW(ord('u'), 0, PLINUSBInitHardware)
30513
PLIORSTHW = IO(ord('u'), 1)

0 commit comments

Comments
 (0)