Skip to content

Commit 02ab9a6

Browse files
committed
added UDSonLIN example
1 parent 4f158dd commit 02ab9a6

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

examples/pyjabi/UDSonLIN.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import jabi
2+
import time
3+
4+
class UDSonLIN:
5+
COMMANDER_ID = 0x3C
6+
RESPONDER_ID = 0x3D
7+
8+
def __init__(self, dev, nad, rate=19200):
9+
dev.lin_set_mode(jabi.LINMode.COMMANDER)
10+
dev.lin_set_rate(rate)
11+
dev.lin_set_filter(self.RESPONDER_ID, 8, jabi.LINChecksum.CLASSIC)
12+
self.dev = dev
13+
self.nad = nad
14+
15+
# low-level
16+
def _write_raw(self, data):
17+
assert(len(data) == 8)
18+
self.dev.lin_write(jabi.LINMessage(self.COMMANDER_ID, list(data), jabi.LINChecksum.CLASSIC))
19+
20+
def _read_raw(self):
21+
msg = self.dev.lin_read(self.RESPONDER_ID)
22+
assert(msg.data[0] == self.nad)
23+
assert((msg.data[1] >> 4) <= 2)
24+
return bytes(msg.data)
25+
26+
# transport layer
27+
def _write(self, data):
28+
assert(len(data) <= 4095)
29+
if len(data) <= 6:
30+
# SF
31+
self._write_raw(bytes([
32+
self.nad,
33+
0x00 | len(data),
34+
*data,
35+
*(b'\xff' * (6 - len(data)))
36+
]))
37+
else:
38+
# FF
39+
self._write_raw(bytes([
40+
self.nad,
41+
0x10 | (len(data) // 256),
42+
len(data) % 256,
43+
*data[:5]
44+
]))
45+
data = data[5:]
46+
# CF
47+
fc = 1
48+
while data:
49+
self._write_raw(bytes([
50+
self.nad,
51+
0x20 | fc,
52+
*data[:6],
53+
*(b'\xff' * (0 if len(data) >= 6 else (6 - len(data))))
54+
]))
55+
fc = (fc + 1) % 16
56+
data = data[6:]
57+
58+
def _read(self):
59+
pkt = self._read_raw()
60+
assert((pkt[1] >> 4) <= 1)
61+
if (pkt[1] >> 4) == 0:
62+
# SF
63+
length = pkt[1] & 0x0F
64+
assert(length <= 6)
65+
return pkt[2:2+length]
66+
else:
67+
# FF
68+
length = ((pkt[1] & 0x0F) << 8) | pkt[2]
69+
data = pkt[3:]
70+
length -= 5
71+
# CF
72+
fc = 1
73+
while length:
74+
pkt = self._read_raw()
75+
assert((pkt[1] >> 4) == 2)
76+
assert((pkt[1] & 0x0F) == fc)
77+
data += pkt[2:2+min(6,length)]
78+
fc = (fc + 1) % 16
79+
length -= min(6,length)
80+
return data
81+
82+
# UDS layer
83+
# basic info - https://en.wikipedia.org/wiki/Unified_Diagnostic_Services
84+
# read/write DID - https://embetronicx.com/tutorials/automotive/uds-protocol/data-transmission-in-uds-protocol
85+
# routine format - https://embedclogic.com/uds-protocol/uds-remote-activation-of-routine/
86+
# routine subfunc - https://piembsystech.com/uds-protocol/
87+
def _routine(self, id, subfunc, data, delay):
88+
self._write(b'\x31' + subfunc + id.to_bytes(2, 'big') + data)
89+
time.sleep(delay)
90+
pkt = self._read()
91+
assert(len(pkt) >= 4)
92+
assert(pkt[0] == 0x71)
93+
assert(pkt[1] == subfunc[0])
94+
assert(int.from_bytes(pkt[2:4], 'big') == id)
95+
return pkt[4:]
96+
97+
def routine_start(self, id, data, delay=0.0):
98+
return self._routine(id, b'\x01', data, delay)
99+
100+
def routine_stop(self, id, data, delay=0.0):
101+
return self._routine(id, b'\x02', data, delay)
102+
103+
def routine_request_results(self, id, data, delay=0.0):
104+
return self._routine(id, b'\x03', data, delay)
105+
106+
def read_did(self, id, delay=0.0):
107+
self._write(b'\x22' + id.to_bytes(2, 'big'))
108+
time.sleep(delay)
109+
pkt = self._read()
110+
assert(len(pkt) >= 3)
111+
assert(pkt[0] == 0x62)
112+
assert(int.from_bytes(pkt[1:3], 'big') == id)
113+
return pkt[3:]
114+
115+
def write_did(self, id, data, delay=0.0):
116+
self._write(b'\x2e' + id.to_bytes(2, 'big') + data)
117+
time.sleep(delay)
118+
pkt = self._read()
119+
assert(len(pkt) == 3)
120+
assert(pkt[0] == 0x6e)
121+
assert(int.from_bytes(pkt[1:3], 'big') == id)
122+
123+
"""
124+
example usage:
125+
126+
uds = UDSonLIN(jabi.USBInterface.list_devices()[0], 0x00)
127+
uds.read_did(0x0000)
128+
"""

0 commit comments

Comments
 (0)