Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HKG: use platform codes to fuzzy fingerprint #28531

Merged
merged 238 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from 226 commits
Commits
Show all changes
238 commits
Select commit Hold shift + click to select a range
0eb0063
get gas/ev/hev from FW (not all correct, poc)
sshane Jan 12, 2023
407d805
add test for essential ecus for fuzzy fingerprinting
sshane Jan 13, 2023
c9e3d0b
kinda works
sshane Jan 13, 2023
a6176a5
stash
sshane Jan 13, 2023
972fb28
clean up
sshane Jan 13, 2023
08962aa
add code
sshane Jan 13, 2023
bd7a0a2
simpler
sshane Jan 14, 2023
5d228d6
use the function
sshane Jan 14, 2023
644e9b1
test it with our cars
sshane Jan 14, 2023
5a06b8d
no re
sshane Jan 14, 2023
bcc2171
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Feb 13, 2023
624307f
debugging
sshane Feb 13, 2023
0c599a8
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Feb 17, 2023
eafc848
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane May 27, 2023
1778c82
handle empty dict
sshane May 27, 2023
7c08d71
simpl
sshane May 27, 2023
ece7446
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 1, 2023
3a721f1
this is promising
sshane Jun 2, 2023
695d748
needs to allow 1 match
sshane Jun 2, 2023
36b7cce
lay out how this should look
sshane Jun 2, 2023
b8b1140
changes
sshane Jun 2, 2023
0acd45f
executable
sshane Jun 2, 2023
abb086a
some work
sshane Jun 2, 2023
c324c9e
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 2, 2023
cd73c30
use config
sshane Jun 2, 2023
07574de
fuzzy ecus
sshane Jun 2, 2023
ab53865
config test
sshane Jun 2, 2023
0192016
comment and some clean up
sshane Jun 2, 2023
3a64703
test platform codes
sshane Jun 2, 2023
e2a4670
use regex, simpler and fixes bug
sshane Jun 2, 2023
4940975
in func
sshane Jun 2, 2023
5bcf9a1
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 2, 2023
84f2b28
rm bad func
sshane Jun 2, 2023
191b51d
typing for new func and remove old from dc
sshane Jun 2, 2023
221946a
todo done
sshane Jun 2, 2023
d12a73b
tested!
sshane Jun 2, 2023
43a76e3
remove fake platform codes
sshane Jun 2, 2023
f6307f5
thought we needed this, but actually...
sshane Jun 2, 2023
eeb4651
not needed
sshane Jun 2, 2023
00325e4
not applicable any more
sshane Jun 2, 2023
a9d7c26
use config for essential ecus
sshane Jun 3, 2023
69ca6cb
first draft of test to make adding/removing fuzzy FP platform intenti…
sshane Jun 3, 2023
c377706
compile
sshane Jun 3, 2023
f998cad
clean up test
sshane Jun 3, 2023
c4588f4
even cleaner
sshane Jun 3, 2023
4abbfd5
fix default ecus type
sshane Jun 3, 2023
caa0513
temp fix
sshane Jun 3, 2023
fb52edf
this is mostly in tests now
sshane Jun 3, 2023
f5c752a
test every fuzzy ecu fw returns one platform code
sshane Jun 3, 2023
3251b9c
experiment with dates
sshane Jun 3, 2023
06ff98c
Revert "experiment with dates"
sshane Jun 3, 2023
e06101f
clean that up
sshane Jun 3, 2023
c7f1291
comment
sshane Jun 3, 2023
e7348f0
test
sshane Jun 3, 2023
e1a87ae
work on all cars
sshane Jun 3, 2023
4a0ad2f
fix fuzz_fw_fingerprint
sshane Jun 3, 2023
5c42a9c
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 3, 2023
b43d21c
comment
sshane Jun 3, 2023
30d3fda
get first by search
sshane Jun 3, 2023
e1423ff
bit more clean up
sshane Jun 3, 2023
13519c8
and more
sshane Jun 3, 2023
185dd2e
use compiled pattern for nicer syntax
sshane Jun 3, 2023
c5c0495
default
sshane Jun 3, 2023
408cc08
flip dat around, much cleaner
sshane Jun 3, 2023
152a6d9
clean up hyundai test a bit
sshane Jun 3, 2023
cdbdd85
flip order
sshane Jun 3, 2023
44e13ca
rename test and flip subTest
sshane Jun 3, 2023
f443779
fix pylint
sshane Jun 3, 2023
05b23a7
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 3, 2023
39ea55d
revert fw changes
sshane Jun 3, 2023
7bad30a
line
sshane Jun 3, 2023
7f609b7
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 6, 2023
b0eb68b
add original functions to test
sshane Jun 6, 2023
5ba9d02
needs to be a list
sshane Jun 6, 2023
3d82514
cmt
sshane Jun 6, 2023
2909adb
draft (need to count one ecu as a match)
sshane Jun 6, 2023
ebd1a0e
tiny clean up
sshane Jun 6, 2023
b4b2166
todo: date range
sshane Jun 7, 2023
37f23e9
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 7, 2023
78330bc
only in notebook
sshane Jun 7, 2023
1efc2d1
remove comment (still can be either list or set)
sshane Jun 7, 2023
7494e08
same, only notebook
sshane Jun 7, 2023
41f7c15
more consistent signature
sshane Jun 7, 2023
584ed18
copilot inspired
sshane Jun 7, 2023
cc591c4
copilot no good
sshane Jun 7, 2023
f66c79a
test for date parsing
sshane Jun 7, 2023
87bb568
better name
sshane Jun 7, 2023
6c8f0dd
good, now we don't have to worry about the dates mismatching in anoth…
sshane Jun 7, 2023
3c198d9
comment up+
sshane Jun 7, 2023
48c69b2
some stuff
sshane Jun 7, 2023
b2c1fe0
clean up
sshane Jun 7, 2023
beddf61
test
sshane Jun 8, 2023
fa6a00b
comment
sshane Jun 8, 2023
8704b98
use utils
sshane Jun 8, 2023
c083ef8
clean up (utils are cleaner and less buggy)
sshane Jun 8, 2023
3d9696e
clean up (utils are cleaner and less buggy)
sshane Jun 8, 2023
9c21f16
fixup test
sshane Jun 8, 2023
10c9f43
use a dash (prettier) and remove some platforms that can fingerprint …
sshane Jun 8, 2023
f6410e2
compile global pattern
sshane Jun 8, 2023
751589d
same as what we do in values
sshane Jun 8, 2023
e425a7b
remove comments
sshane Jun 8, 2023
ec82b5d
fuzzy_get_platform_codes is one or none here
sshane Jun 8, 2023
112dfbe
more clean up
sshane Jun 8, 2023
f2c431f
sort imports
sshane Jun 8, 2023
3e0bd29
woah woah woah
sshane Jun 8, 2023
79471d1
add comment
sshane Jun 8, 2023
4b38b23
fix reassigning different types
sshane Jun 8, 2023
01ccf3d
add types
sshane Jun 8, 2023
4e52b8a
adapt fuzzy test recently added (nice it caught this!)
sshane Jun 8, 2023
51af0c8
update lock
sshane Jun 8, 2023
1ddf133
options
sshane Jun 8, 2023
ede54cd
stash
sshane Jun 8, 2023
e073462
comments and fixes
sshane Jun 8, 2023
38c5c55
better comments
sshane Jun 8, 2023
17f927e
better
sshane Jun 8, 2023
be319cd
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 8, 2023
af6f99b
test: run on exact fuzzy matching logic, same results!
sshane Jun 8, 2023
9781e19
use match_fw_to_car
sshane Jun 8, 2023
4ca3415
test all fw
sshane Jun 8, 2023
e2cf00c
ex
sshane Jun 8, 2023
b251bb8
unused random
sshane Jun 8, 2023
a7c0869
this is a possibility
sshane Jun 8, 2023
a6b86f2
this is more clear
sshane Jun 9, 2023
b4b74fb
fix
sshane Jun 9, 2023
2f3cc88
revert
sshane Jun 9, 2023
0c66259
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 9, 2023
c80a964
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 9, 2023
caaa7db
revert to needing both ECUs to match to reduce false positives, test
sshane Jun 9, 2023
cc26cb0
fix excluded platform test :( but it's ok
sshane Jun 9, 2023
f4b46eb
add comment
sshane Jun 9, 2023
e76bd01
we actually want to only test fuzzy ecus to make it explicit
sshane Jun 9, 2023
675ed2b
fix mypy
sshane Jun 9, 2023
603bed3
comment for tomorrow
sshane Jun 9, 2023
068ce63
just add matches with fuzzy FP
sshane Jun 9, 2023
7a29bad
add comment
sshane Jun 9, 2023
16f490b
this was the cleanest I could think of, but still working on it. not …
sshane Jun 9, 2023
11946df
think this is better, but also worse...
sshane Jun 9, 2023
589ba6b
comment: reframing how this works
sshane Jun 9, 2023
cbe1d55
revert back to what we did before
sshane Jun 9, 2023
1bd6bf9
was swapped
sshane Jun 9, 2023
661de4f
else set
sshane Jun 9, 2023
73d7c1c
remove old comment
sshane Jun 9, 2023
7c44fbb
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 10, 2023
14114aa
fixes from merge
sshane Jun 10, 2023
ce10c6c
remove fuzzy_min_match_count from this pr
sshane Jun 10, 2023
49959c6
fix static analysis
sshane Jun 10, 2023
5835570
also unused
sshane Jun 10, 2023
b911390
different method first draft
sshane Jun 13, 2023
34c8c05
copy existing fuzzy func
sshane Jun 13, 2023
d3e918f
check all possible ecus exist, only platform codes, slightly refactor…
sshane Jun 13, 2023
5cdb7bd
fix
sshane Jun 13, 2023
16d8541
Revert recent
sshane Jun 13, 2023
7b29aed
Merge remote-tracking branch 'upstream/master' into hkg-fuzzy
sshane Jun 13, 2023
c759a08
new func
sshane Jun 13, 2023
d07a879
fixup test
sshane Jun 13, 2023
92cf41c
remove changes from v1 from fw_versions.py
sshane Jun 13, 2023
3ef0e80
Merge remote-tracking branch 'upstream/master' into hkz-fuzzy-2
sshane Jun 13, 2023
538e18e
clean up a bit
sshane Jun 13, 2023
95e1711
return part as part of code
sshane Jun 13, 2023
272c8bd
fix test
sshane Jun 13, 2023
0247c52
add original fuzzy function
sshane Jun 13, 2023
864f80d
add an ecu match if the date is within range (or date doesn't exist)
sshane Jun 13, 2023
76ca2a1
add format for what we're going to do
sshane Jun 13, 2023
6b12c01
not working stash
sshane Jun 13, 2023
27f44b4
the exact matching function does more of what we want with less code …
sshane Jun 14, 2023
50e65ad
we don't care about found versions, only codes and dates
sshane Jun 14, 2023
8a0662e
actually we do have an exception
sshane Jun 14, 2023
fb0f24d
this works pretty nicely now
sshane Jun 14, 2023
1f58dbf
up here
sshane Jun 14, 2023
8692297
this is better
sshane Jun 14, 2023
1c0b92f
some minor clean up
sshane Jun 14, 2023
16cf8a1
old function=now junk
sshane Jun 14, 2023
c611281
fix platform code test
sshane Jun 14, 2023
ae8e1df
remove old platform code function
sshane Jun 14, 2023
503be25
now rename _new to
sshane Jun 14, 2023
0ea406b
use FW_QUERY_CONFIG
sshane Jun 14, 2023
f781b62
clean up imports
sshane Jun 14, 2023
62aaaf4
rename that too
sshane Jun 14, 2023
6b7caf5
one line
sshane Jun 14, 2023
458f2f3
correct typing
sshane Jun 14, 2023
2ac5970
draft tests
sshane Jun 14, 2023
7cf618a
so that works
sshane Jun 14, 2023
7f4ca41
fixup excluded platform test now too
sshane Jun 14, 2023
6a1e138
this is tested by excluded platform test
sshane Jun 14, 2023
7c5d0ac
test parts and dates
sshane Jun 14, 2023
4f0ffbc
remove old comment
sshane Jun 14, 2023
52e5122
old import
sshane Jun 14, 2023
13a0970
take platform code stuff out of FwQueryConfig
sshane Jun 14, 2023
94a3ec1
fix test
sshane Jun 14, 2023
9c868b3
revert debug script
sshane Jun 14, 2023
3de56d5
flip order
sshane Jun 14, 2023
30ff802
make this a set by default
sshane Jun 14, 2023
35fb88e
revert this part
sshane Jun 14, 2023
2b22337
Merge remote-tracking branch 'upstream/master' into hkz-fuzzy-2
sshane Jun 14, 2023
60aeb19
correct typing
sshane Jun 14, 2023
d549684
clean up comments
sshane Jun 14, 2023
10ff0f4
clean that test up too/pylint
sshane Jun 14, 2023
edd25f6
combine these three tests ina clean way
sshane Jun 14, 2023
3845d66
not right
sshane Jun 14, 2023
5fbe21f
more general
sshane Jun 14, 2023
51958c7
be consistent with quotes
sshane Jun 14, 2023
b613b15
Merge remote-tracking branch 'upstream/master' into hkz-fuzzy-2
sshane Jun 14, 2023
94f7647
comment
sshane Jun 14, 2023
43685d2
comment
sshane Jun 14, 2023
ed8d0b6
comment in fw_versions
sshane Jun 14, 2023
387cb65
flip order
sshane Jun 14, 2023
e7cfa56
this is more readable
sshane Jun 14, 2023
e14e383
could test all this, but it's tested in test_hyundai and doesn't do a…
sshane Jun 14, 2023
634f57b
only assert brands which use this
sshane Jun 14, 2023
ca755d8
invalidate all CAN FD ICE and hybrid
sshane Jun 14, 2023
6025a0f
tuple
sshane Jun 14, 2023
498ec28
can get away without filtering
sshane Jun 14, 2023
f1dcbbc
add comment reasons
sshane Jun 14, 2023
d7f838f
fix
sshane Jun 14, 2023
794bb55
Merge remote-tracking branch 'upstream/master' into hkz-fuzzy-2
sshane Jun 14, 2023
0af5e1e
some review suggestions
sshane Jun 14, 2023
cd204a1
this works (first draft)
sshane Jun 14, 2023
adf7b73
this is better
sshane Jun 14, 2023
78f13c4
script to print platform codes and dates
sshane Jun 14, 2023
426a840
sanity check for dates are in correct ecus and platforms
sshane Jun 14, 2023
98d9c75
mypy
sshane Jun 14, 2023
1f307e6
Merge remote-tracking branch 'upstream/master' into hkz-fuzzy-2
sshane Jun 14, 2023
c0c82ed
better variable name and comment
sshane Jun 14, 2023
ef7cac8
rename
sshane Jun 14, 2023
0906df2
same
sshane Jun 14, 2023
6094058
slightly better name
sshane Jun 14, 2023
b00a7c2
subset
sshane Jun 15, 2023
c55b8db
exclude platforms and live car without dates
sshane Jun 15, 2023
828b48e
consistent
sshane Jun 15, 2023
8ad75ff
self explan
sshane Jun 15, 2023
9fd9288
better name
sshane Jun 15, 2023
eeac0dc
Merge remote-tracking branch 'upstream/master' into hkz-fuzzy-2
sshane Jun 15, 2023
e670eb7
test to make sure the functions agree
sshane Jun 15, 2023
f6ecb22
clean that up
sshane Jun 15, 2023
248d925
Merge remote-tracking branch 'upstream/master' into hkz-fuzzy-2
sshane Jun 15, 2023
b2ff3d6
comment
sshane Jun 15, 2023
0c0ea18
we get other responses from queries not in DB, only check any
sshane Jun 15, 2023
82ee14a
not used or typed
sshane Jun 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion selfdrive/car/fw_query_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import copy
from dataclasses import dataclass, field
import struct
from typing import Dict, List, Optional, Tuple
from typing import Callable, Dict, List, Optional, Set, Tuple

import panda.python.uds as uds

Expand Down Expand Up @@ -74,6 +74,9 @@ class FwQueryConfig:
non_essential_ecus: Dict[capnp.lib.capnp._EnumModule, List[str]] = field(default_factory=dict)
# Ecus added for data collection, not to be fingerprinted on
extra_ecus: List[Tuple[capnp.lib.capnp._EnumModule, int, Optional[int]]] = field(default_factory=list)
# Function a brand can implement to provide better fuzzy matching. Takes in FW versions,
# returns set of candidates. Only will match if one candidate is returned
match_fw_to_car_fuzzy: Optional[Callable[[Dict[Tuple[int, Optional[int]], Set[bytes]]], Set[str]]] = None

def __post_init__(self):
for i in range(len(self.requests)):
Expand Down
5 changes: 5 additions & 0 deletions selfdrive/car/fw_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ def match_fw_to_car(fw_versions, allow_exact=True, allow_fuzzy=True, log=True):
fw_versions_dict = build_fw_dict(fw_versions, filter_brand=brand)
matches |= match_func(fw_versions_dict, log=log)

# If specified and no matches so far, fall back to brand's fuzzy fingerprinting function
config = FW_QUERY_CONFIGS[brand]
if not exact_match and not len(matches) and config.match_fw_to_car_fuzzy is not None:
matches |= config.match_fw_to_car_fuzzy(fw_versions_dict)

if len(matches):
return exact_match, matches

Expand Down
11 changes: 3 additions & 8 deletions selfdrive/car/hyundai/tests/print_platform_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,9 @@
if ecu[0] not in PLATFORM_CODE_ECUS:
continue

codes = set()
dates = set()
for fw in ecus[ecu]:
code = list(get_platform_codes([fw]))[0]
codes.add(code.split(b"-")[0])
if b"-" in code:
dates.add(code.split(b"-")[1])

platform_codes = get_platform_codes(ecus[ecu])
codes = {code for code, _ in platform_codes}
dates = {date for _, date in platform_codes if date is not None}
print(f' (Ecu.{ECU_NAME[ecu[0]]}, {hex(ecu[1])}, {ecu[2]}):')
print(f' Codes: {codes}')
print(f' Dates: {dates}')
94 changes: 73 additions & 21 deletions selfdrive/car/hyundai/tests/test_hyundai.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import unittest

from cereal import car
from selfdrive.car.hyundai.values import CAMERA_SCC_CAR, CANFD_CAR, CAN_GEARS, CAR, CHECKSUM, FW_QUERY_CONFIG, \
FW_VERSIONS, LEGACY_SAFETY_MODE_CAR, PART_NUMBER_FW_PATTERN, PLATFORM_CODE_ECUS, \
from selfdrive.car.fw_versions import build_fw_dict
from selfdrive.car.hyundai.values import CAMERA_SCC_CAR, CANFD_CAR, CAN_GEARS, CAR, CHECKSUM, EV_CAR, \
FW_QUERY_CONFIG, FW_VERSIONS, LEGACY_SAFETY_MODE_CAR, PLATFORM_CODE_ECUS, \
get_platform_codes

Ecu = car.CarParams.Ecu
Expand Down Expand Up @@ -50,6 +51,30 @@ def test_fw_format(self):
# - every supported ECU FW version has a part number
# - expected parsing of ECU FW dates

# Some platforms have date codes in a different format we don't yet parse (or are missing).
# For now, assert list of expected missing date cars
no_dates_platforms = {
# CAN FD
CAR.TUCSON_4TH_GEN,
CAR.TUCSON_HYBRID_4TH_GEN,
CAR.KIA_SPORTAGE_HYBRID_5TH_GEN,
CAR.SANTA_CRUZ_1ST_GEN,
CAR.KIA_SPORTAGE_5TH_GEN,
# CAN
CAR.KONA,
CAR.SONATA_LF,
CAR.VELOSTER,
CAR.KIA_CEED,
CAR.KIA_FORTE,
CAR.KONA_EV,
CAR.KONA_EV_2022,
CAR.KIA_OPTIMA_G4,
CAR.KIA_OPTIMA_G4_FL,
CAR.ELANTRA,
CAR.KONA_HEV,
CAR.KIA_SORENTO,
}

for car_model, ecus in FW_VERSIONS.items():
with self.subTest(car_model=car_model):
for ecu, fws in ecus.items():
Expand All @@ -62,48 +87,75 @@ def test_fw_format(self):
self.assertEqual(1, len(result), f"Unable to parse FW: {fw}")
codes |= result

# Some newer platforms have date codes in a different format we don't yet parse,
# for now assert we can parse all FW or none
self.assertEqual(len({b"-" in code for code in codes}), 1,
"Not all FW dates are parsable")
# So far we've only seen dates in fwdCamera
if car_model in no_dates_platforms or ecu[0] != Ecu.fwdCamera:
self.assertTrue(all({date is None for _, date in codes}))
else:
self.assertTrue(all({date is not None for _, date in codes}))

if car_model == CAR.HYUNDAI_GENESIS:
raise unittest.SkipTest("No part numbers for car model")

# Hyundai places the ECU part number in their FW versions, assert all parsable
# Some examples of valid formats: b"56310-L0010", b"56310L0010", b"56310/M6300"
for fw in fws:
match = PART_NUMBER_FW_PATTERN.search(fw)
self.assertIsNotNone(match, fw)
self.assertTrue(all({b"-" in code for code, _ in codes}),
f"FW does not have part number: {fw}")

def test_platform_codes_spot_check(self):
# Asserts basic platform code parsing behavior for a few cases
codes = get_platform_codes([b"\xf1\x00DH LKAS 1.1 -150210"])
self.assertEqual(codes, {b"DH-1502"})
results = get_platform_codes([b"\xf1\x00DH LKAS 1.1 -150210"])
self.assertEqual(results, {(b"DH", b"150210")})

# Some cameras and all radars do not have dates
codes = get_platform_codes([b"\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 "])
self.assertEqual(codes, {b"AEhe"})
results = get_platform_codes([b"\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 "])
self.assertEqual(results, {(b"AEhe-G2000", None)})

codes = get_platform_codes([b"\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 "])
self.assertEqual(codes, {b"CV1"})
results = get_platform_codes([b"\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 "])
self.assertEqual(results, {(b"CV1-CV000", None)})

codes = get_platform_codes([
results = get_platform_codes([
b"\xf1\x00DH LKAS 1.1 -150210",
b"\xf1\x00AEhe SCC H-CUP 1.01 1.01 96400-G2000 ",
b"\xf1\x00CV1_ RDR ----- 1.00 1.01 99110-CV000 ",
])
self.assertEqual(codes, {b"DH-1502", b"AEhe", b"CV1"})
self.assertEqual(results, {(b"DH", b"150210"), (b"AEhe-G2000", None), (b"CV1-CV000", None)})

# Returned platform codes must inclusively contain start/end dates
codes = get_platform_codes([
results = get_platform_codes([
b"\xf1\x00LX2 MFC AT USA LHD 1.00 1.07 99211-S8100 220222",
b"\xf1\x00LX2 MFC AT USA LHD 1.00 1.08 99211-S8100 211103",
b"\xf1\x00ON MFC AT USA LHD 1.00 1.01 99211-S9100 190405",
b"\xf1\x00ON MFC AT USA LHD 1.00 1.03 99211-S9100 190720",
])
self.assertEqual(codes, {b"LX2-2111", b"LX2-2112", b"LX2-2201", b"LX2-2202",
b"ON-1904", b"ON-1905", b"ON-1906", b"ON-1907"})
self.assertEqual(results, {(b"LX2-S8100", b"220222"), (b"LX2-S8100", b"211103"),
(b"ON-S9100", b"190405"), (b"ON-S9100", b"190720")})

def test_excluded_platforms(self):
# Asserts a list of platforms that will not fuzzy fingerprint with platform codes due to them being shared.
# This list can be shrunk as we combine platforms and detect features
excluded_platforms = {
CAR.GENESIS_G70, # shared platform code, part number, and date
CAR.GENESIS_G70_2020,
CAR.TUCSON_4TH_GEN, # shared platform code and part number
CAR.TUCSON_HYBRID_4TH_GEN,
} | set(CANFD_CAR - EV_CAR) # shared platform codes

platforms_with_shared_codes = set()
for platform, fw_by_addr in FW_VERSIONS.items():
car_fw = []
for ecu, fw_versions in fw_by_addr.items():
ecu_name, addr, sub_addr = ecu
for fw in fw_versions:
car_fw.append({"ecu": ecu_name, "fwVersion": fw, "address": addr,
"subAddress": 0 if sub_addr is None else sub_addr})

CP = car.CarParams.new_message(carFw=car_fw)
matches = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(build_fw_dict(CP.carFw))
if len(matches) == 1:
self.assertEqual(list(matches)[0], platform)
else:
platforms_with_shared_codes.add(platform)

self.assertEqual(platforms_with_shared_codes, excluded_platforms)


if __name__ == "__main__":
Expand Down
89 changes: 62 additions & 27 deletions selfdrive/car/hyundai/values.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import re
from datetime import datetime
from dateutil import rrule
from collections import defaultdict
from dataclasses import dataclass
from enum import Enum, IntFlag
from typing import DefaultDict, Dict, List, Optional, Set, Union, cast
from typing import Dict, List, Optional, Set, Tuple, Union

from cereal import car
from panda.python import uds
from common.conversions import Conversions as CV
from selfdrive.car import dbc_dict
from selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column
from selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16
from system.swaglog import cloudlog

Ecu = car.CarParams.Ecu

Expand Down Expand Up @@ -348,35 +344,72 @@ class Buttons:
}


def get_platform_codes(fw_versions: List[bytes]) -> Set[bytes]:
codes: DefaultDict[bytes, Set[Optional[bytes]]] = defaultdict(set)
def get_platform_codes(fw_versions: List[bytes]) -> Set[Tuple[bytes, Optional[bytes]]]:
sshane marked this conversation as resolved.
Show resolved Hide resolved
# Returns unique, platform-specific identification codes for a set of versions
codes = set() # (code-Optional[part], date)
for fw in fw_versions:
code_match, date_match = (PLATFORM_CODE_FW_PATTERN.search(fw),
DATE_FW_PATTERN.search(fw))
code_match = PLATFORM_CODE_FW_PATTERN.search(fw)
part_match = PART_NUMBER_FW_PATTERN.search(fw)
date_match = DATE_FW_PATTERN.search(fw)
if code_match is not None:
code = code_match.group()
code: bytes = code_match.group()
part = part_match.group() if part_match else None
date = date_match.group() if date_match else None
codes[code].add(date)
if part is not None:
# part number starts with generic ECU part type, add what is specific to platform
code += b"-" + part[-5:]

# Create platform codes for all dates inclusive if ECU has FW dates
final_codes = set()
for code, dates in codes.items():
# Radar and some cameras don't have FW dates
if None in dates:
final_codes.add(code)
continue
codes.add((code, date))
return codes

try:
parsed = {datetime.strptime(cast(bytes, date).decode()[:4], '%y%m') for date in dates}
except ValueError:
cloudlog.exception(f'Error parsing date in FW versions: {code!r}, {dates}')
final_codes.add(code)
continue

for monthly in rrule.rrule(rrule.MONTHLY, dtstart=min(parsed), until=max(parsed)):
final_codes.add(code + b'-' + monthly.strftime('%y%m').encode())
def match_fw_to_car_fuzzy(live_fw_versions, log=True) -> Set[str]:
# Non-electric CAN FD platforms often do not have platform code specifiers needed
# to distinguish between hybrid and ICE. All EVs so far are either exclusively
# electric or specify electric in the platform code.
fuzzy_platform_blacklist = set(CANFD_CAR - EV_CAR)
candidates = set()

return final_codes
for candidate, fws in FW_VERSIONS.items():
# Keep track of ECUs which pass all checks (platform codes, within date range)
valid_found_ecus = set()
valid_expected_ecus = {ecu[1:] for ecu in fws if ecu[0] in PLATFORM_CODE_ECUS}
for ecu, expected_versions in fws.items():
addr = ecu[1:]
# Only check ECUs expected to have platform codes
if ecu[0] not in PLATFORM_CODE_ECUS:
continue

# Expected platform codes & dates
codes = get_platform_codes(expected_versions)
expected_platform_codes = {code for code, _ in codes}
expected_dates = {date for _, date in codes if date is not None}

# Found platform codes & dates
codes = get_platform_codes(live_fw_versions.get(addr, set()))
found_platform_codes = {code for code, _ in codes}
found_dates = {date for _, date in codes if date is not None}

# Check platform code + part number matches for any found versions
if not any(found_platform_code in expected_platform_codes for found_platform_code in found_platform_codes):
break

# Don't check dates if none in database
sshane marked this conversation as resolved.
Show resolved Hide resolved
if len(expected_dates):
sshane marked this conversation as resolved.
Show resolved Hide resolved
if not len(found_dates):
break

# Check all dates within range in the database, format is %y%m%d
if not all(min(expected_dates) <= found_date <= max(expected_dates) for found_date in found_dates):
break

valid_found_ecus.add(addr)

# If all live ECUs pass all checks for candidate, add it as a match
if len(valid_expected_ecus - valid_found_ecus) == 0:
sshane marked this conversation as resolved.
Show resolved Hide resolved
candidates.add(candidate)

return candidates - fuzzy_platform_blacklist


HYUNDAI_VERSION_REQUEST_LONG = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \
Expand Down Expand Up @@ -458,6 +491,8 @@ def get_platform_codes(fw_versions: List[bytes]) -> Set[bytes]:
(Ecu.hvac, 0x7b3, None), # HVAC Control Assembly
(Ecu.cornerRadar, 0x7b7, None),
],
# Custom fuzzy fingerprinting function using platform codes, part numbers + FW dates:
match_fw_to_car_fuzzy=match_fw_to_car_fuzzy,
)

FW_VERSIONS = {
Expand Down