Skip to content

Commit ccdf9ff

Browse files
author
Brendan Whitfield
committed
added frame sequence number processing, fixed frame ordering bug in legacy protocol
1 parent a00281b commit ccdf9ff

4 files changed

Lines changed: 40 additions & 4 deletions

File tree

obd/elm327.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def __find_primary_ecu(self, messages):
188188
# first, try filtering for the standard ECU IDs
189189
test = lambda m: m.tx_id == self.__protocol.PRIMARY_ECU
190190

191-
if bool(filter(test, messages)):
191+
if bool([m for m in messages if test(m)]):
192192
return self.__protocol.PRIMARY_ECU
193193
else:
194194
# last resort solution, choose ECU

obd/protocols/protocol_can.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,35 @@ def create_message(self, frames, tx_id):
152152
debug("Never received frame marked CF")
153153
return None
154154

155-
# TODO
155+
# calculate proper sequence indices from the lower 4 bits given
156+
for prev, curr in zip(cf, cf[1:]):
157+
# Frame sequence numbers only specify the low order bits, so compute the
158+
# full sequence number from the frame number and the last sequence number seen:
159+
# 1) take the high order bits from the last_sn and low order bits from the frame
160+
seq = (prev.seq_index & ~0x0F) + (curr.seq_index)
161+
# 2) if this is more than 7 frames away, we probably just wrapped (e.g.,
162+
# last=0x0F current=0x01 should mean 0x11, not 0x01)
163+
if seq < prev.seq_index - 7:
164+
# untested
165+
seq += 0x10
166+
167+
curr.seq_index = seq
168+
169+
# sort the sequence indices
170+
cf = sorted(cf, key=lambda f: f.seq_index)
171+
172+
# concat these lists together
173+
frames = ff + cf
174+
175+
# ensure that each order byte is consecutive by looking at
176+
# them in pairs. (see if anything's missing)
177+
indices = [f.seq_index for f in frames]
178+
pairs = zip(indices, indices[1:])
179+
if not all([p[0]+1 == p[1] for p in pairs]):
180+
debug("Recieved multiline response with missing frames")
181+
return None
156182

183+
# TODO: extract message data
157184

158185

159186
# chop off the Mode/PID bytes based on the mode number

obd/protocols/protocol_legacy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ def create_message(self, frames, tx_id):
114114
# etc... [] [ Data ]
115115

116116
# sort the frames by the order byte
117-
frames = sorted(frames, key=lambda f: f[2])
117+
frames = sorted(frames, key=lambda f: f.data_bytes[2])
118118

119119
# ensure that each order byte is consecutive by looking at
120120
# them in pairs. (see if anything's missing)
121-
indices = [f[2] for f in frames]
121+
indices = [f.data_bytes[2] for f in frames]
122122
pairs = zip(indices, indices[1:])
123123
if not all([p[0]+1 == p[1] for p in pairs]):
124124
debug("Recieved multiline response with missing frames")

tests/test_protocols.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ def test_can_11():
100100
r = p(["NO DATA", "NO DATA"])
101101
assert len(r) == 0
102102

103+
# multi-line response
104+
'''
105+
r = p(["7E8 10 13 49 04 01 35 36 30",
106+
"7E8 21 32 38 39 34 39 41 43",
107+
"7E8 22 00 00 00 00 00 00 31"
108+
])
109+
assert len(r) == 1
110+
'''
111+
103112

104113
def test_can_29():
105114
pass

0 commit comments

Comments
 (0)