openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
5.9 KiB

#!/usr/bin/env python3
Ford: use platform codes to fuzzy fingerprint (#31124) * Ford: use platform codes to fuzzy fingerprint TODO: write scripts/tests (print platform codes and version ranges etc.) May close #31052 * get_platform_codes: fix return type * add print_platform_codes.py script * print_platform_codes: sort versions * match_fw_to_car_fuzzy: use set comprehension, and fix typo * Ford: add missing Mach-E fw From the route 83a4e056c7072678/2023-11-13--16-51-33 (which is already in selfdrive/car/tests/routes.py, added in #30691). * add ford_fuzzy_fingerprint.ipynb notebook * get_platform_codes: use regex to parse firmware * test_ford: test_platform_codes_fuzzy_fw * test_ford: use get_platform_codes in test_fw_versions * match_fw_to_car_fuzzy: improve comments * test_ford: add test_platform_codes_spot_check * test_ford: add test_match_fw_fuzzy * remove comment from notebook * TestFordFW: remove engine ECU FW * update print_platform_codes.py * remove part number (unecessary) * platform codes can just use platform hint and model year - software revision not useful * fuzzy FP on the platform hint and model year hint range * fix platform codes test * update notebook * add notebook * explain model year hint better * test part numbers again * cleanup notebooks * remove notebook * cleanup match_fw_to_car_fuzzy and add comments * update comment * . * Revert "remove notebook" This reverts commit 5d4ca202f2a23601d5c829204119f36a58f2b451. * add notebook back * remove PSCM from PLATFORM_CODE_ECUS ABS and IPMA are the best for uniquely matching, and the radar is always required * Revert "remove PSCM from PLATFORM_CODE_ECUS" This reverts commit b7baeac19c18b5aa0c31da52f12054f4bae6e1ff. * fix from merge * more fixes revert * FW_RE -> FW_PATTERN * this can actually be set * conventions * just add * convention * refactor matcher, this brings it more in line with Hyundai. IMPORTANT NOTE: NOTE THAT WE remove the separation for the different platform code model year hint ranges, I don't see that being a problem * better/smaller test * add test to catch overlapping platform codes * remove nb * not now --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: 85c9fea5d8e3f5ee673317e15df958a7168a899d
12 months ago
import random
import unittest
from collections.abc import Iterable
import capnp
Ford: use platform codes to fuzzy fingerprint (#31124) * Ford: use platform codes to fuzzy fingerprint TODO: write scripts/tests (print platform codes and version ranges etc.) May close #31052 * get_platform_codes: fix return type * add print_platform_codes.py script * print_platform_codes: sort versions * match_fw_to_car_fuzzy: use set comprehension, and fix typo * Ford: add missing Mach-E fw From the route 83a4e056c7072678/2023-11-13--16-51-33 (which is already in selfdrive/car/tests/routes.py, added in #30691). * add ford_fuzzy_fingerprint.ipynb notebook * get_platform_codes: use regex to parse firmware * test_ford: test_platform_codes_fuzzy_fw * test_ford: use get_platform_codes in test_fw_versions * match_fw_to_car_fuzzy: improve comments * test_ford: add test_platform_codes_spot_check * test_ford: add test_match_fw_fuzzy * remove comment from notebook * TestFordFW: remove engine ECU FW * update print_platform_codes.py * remove part number (unecessary) * platform codes can just use platform hint and model year - software revision not useful * fuzzy FP on the platform hint and model year hint range * fix platform codes test * update notebook * add notebook * explain model year hint better * test part numbers again * cleanup notebooks * remove notebook * cleanup match_fw_to_car_fuzzy and add comments * update comment * . * Revert "remove notebook" This reverts commit 5d4ca202f2a23601d5c829204119f36a58f2b451. * add notebook back * remove PSCM from PLATFORM_CODE_ECUS ABS and IPMA are the best for uniquely matching, and the radar is always required * Revert "remove PSCM from PLATFORM_CODE_ECUS" This reverts commit b7baeac19c18b5aa0c31da52f12054f4bae6e1ff. * fix from merge * more fixes revert * FW_RE -> FW_PATTERN * this can actually be set * conventions * just add * convention * refactor matcher, this brings it more in line with Hyundai. IMPORTANT NOTE: NOTE THAT WE remove the separation for the different platform code model year hint ranges, I don't see that being a problem * better/smaller test * add test to catch overlapping platform codes * remove nb * not now --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: 85c9fea5d8e3f5ee673317e15df958a7168a899d
12 months ago
from hypothesis import settings, given, strategies as st
from parameterized import parameterized
from cereal import car
Ford: use platform codes to fuzzy fingerprint (#31124) * Ford: use platform codes to fuzzy fingerprint TODO: write scripts/tests (print platform codes and version ranges etc.) May close #31052 * get_platform_codes: fix return type * add print_platform_codes.py script * print_platform_codes: sort versions * match_fw_to_car_fuzzy: use set comprehension, and fix typo * Ford: add missing Mach-E fw From the route 83a4e056c7072678/2023-11-13--16-51-33 (which is already in selfdrive/car/tests/routes.py, added in #30691). * add ford_fuzzy_fingerprint.ipynb notebook * get_platform_codes: use regex to parse firmware * test_ford: test_platform_codes_fuzzy_fw * test_ford: use get_platform_codes in test_fw_versions * match_fw_to_car_fuzzy: improve comments * test_ford: add test_platform_codes_spot_check * test_ford: add test_match_fw_fuzzy * remove comment from notebook * TestFordFW: remove engine ECU FW * update print_platform_codes.py * remove part number (unecessary) * platform codes can just use platform hint and model year - software revision not useful * fuzzy FP on the platform hint and model year hint range * fix platform codes test * update notebook * add notebook * explain model year hint better * test part numbers again * cleanup notebooks * remove notebook * cleanup match_fw_to_car_fuzzy and add comments * update comment * . * Revert "remove notebook" This reverts commit 5d4ca202f2a23601d5c829204119f36a58f2b451. * add notebook back * remove PSCM from PLATFORM_CODE_ECUS ABS and IPMA are the best for uniquely matching, and the radar is always required * Revert "remove PSCM from PLATFORM_CODE_ECUS" This reverts commit b7baeac19c18b5aa0c31da52f12054f4bae6e1ff. * fix from merge * more fixes revert * FW_RE -> FW_PATTERN * this can actually be set * conventions * just add * convention * refactor matcher, this brings it more in line with Hyundai. IMPORTANT NOTE: NOTE THAT WE remove the separation for the different platform code model year hint ranges, I don't see that being a problem * better/smaller test * add test to catch overlapping platform codes * remove nb * not now --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: 85c9fea5d8e3f5ee673317e15df958a7168a899d
12 months ago
from openpilot.selfdrive.car.fw_versions import build_fw_dict
from openpilot.selfdrive.car.ford.values import CAR, FW_QUERY_CONFIG, FW_PATTERN, get_platform_codes
from openpilot.selfdrive.car.ford.fingerprints import FW_VERSIONS
Ecu = car.CarParams.Ecu
ECU_ADDRESSES = {
Ecu.eps: 0x730, # Power Steering Control Module (PSCM)
Ecu.abs: 0x760, # Anti-Lock Brake System (ABS)
Ecu.fwdRadar: 0x764, # Cruise Control Module (CCM)
Ecu.fwdCamera: 0x706, # Image Processing Module A (IPMA)
Ecu.engine: 0x7E0, # Powertrain Control Module (PCM)
Ecu.shiftByWire: 0x732, # Gear Shift Module (GSM)
Ford: log interesting module configuration data (#31569) * Ford: log interesting module configuration data Ford ECUs have what is called "As-Built Data" which is configured at the factory/workshop to set what packages/features are enabled on the car. But they also contain vehicle specific information (VIN, make, model, weight, wheel base...), DTC information and driver preferences. I dumped the CAN traffic for the FORScan diagnostic tool to see how it requests this information from the ECUs. <details> <summary>FORScan communication with IPMA (camera)</summary> <pre> {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': '0200'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'TESTER_PRESENT', 'hex': '00'} {'addr': 1806, 'type': 'positive_response', 'service': 'TESTER_PRESENT', 'hex': '00'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f190'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f113'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x13JX7T-19H406-CH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1134a5837542d3139483430362d434800000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f188'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x88JX7T-14F397-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1884a5837542d3134463339372d414800000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f120'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1 JX7T-14F397-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1204a5837542d3134463339372d424600000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f121'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f124'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1$JX7T-14F398-AG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1244a5837542d3134463339382d414700000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f125'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1%JX7T-14F398-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1254a5837542d3134463339382d424600000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f126'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f10a'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f111'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x11JX7T-14F403-CA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1114a5837542d3134463430332d434100000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f18c'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x8c182762191\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f18c31383237363231393100000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f162'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f110'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x10DS-JX7T-19H406-AD\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f11044532d4a5837542d3139483430362d414400000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': '0202'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd100'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd10001'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd700'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd70001010101'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd701'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd70101020000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'dd01'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'dd010102f8'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f113'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x13JX7T-19H406-CH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1134a5837542d3139483430362d434800000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd08'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd0800000500500100300000000000000000000000300000000000000000200100400300100200001200f00300500000000000000300c00b00400200000000000000000000000000000000200f01201e01501400a00200200400700d02501d01700700e06405005e05503401100a000000002002002001000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd09'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd09ffec0001fef60002'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DTC_INFORMATION', 'hex': '028f'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DTC_INFORMATION', 'hex': '02ff50019768c253002cc401862cc418862c'} ... skip DTC requests ... {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de01'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de01fd5616db5fffff557fe1f842080000000800000008000000080000000819bfe00f7c00000000000000000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de02'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de02800000008000000080000000800000008337fc00800000008000000080000000800000008337fc0000000000000000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de03'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de03fffc26c3800000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de04'} {'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de04546a8c0000000000'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de05'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de06'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de07'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de08'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de09'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0a'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0b'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0c'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0d'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} {'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0e'} {'addr': 1806, 'type': 'negative_response', 'hex': '2231'} </pre> </details> Using UDS service `READ_DATA_BY_IDENTIFIER`, we can read the As-Built blocks from `0xDExx` with no diagnostic session/security access necessary. I used [Online As-Built databases](https://cyanlabs.net/asbuilt-db/) and various coding spreadsheets shared online to find values we might be interested in using for fingerprinting (both vehicle parameters and identifying the platform). ABS: - Payload tier (Base, Mid Payload Upgrade, Heavy Duty Payload Upgrade...) - Wheelbase - Steering ratio - Cruise Control Mode (Normal, Adaptive) - Enable Stop and Go PSCM: - Enable Lane Keeping Aid - Enable Traffic Jam Assist - Enable Lane Centering Assist IPMA (Q4): - Steering ratio - Wheelbase APIM (Sync 3 and Sync 4): - Steering ratio - Vehicle weight - Wheelbase There are more potentially useful signals which I haven't included although they might not be necessary: - Vehicle (Ford platform code, like "C344" or "C519" - although the source of the mapping from index to code is FORScan and not Ford themselves unless we can find a better source). - Fuel type - Vehicle length/height/front track/rear track - Tire circumference (could be useful for converting wheel speed rad/s to m/s) - Steering angle source (Pinion, Wheel) - Country code (letters, e.g. US, CA or UK) - Transmission type - CAN network architecture - More feature flags (the APIM also stores settings for ACC, LCA, BLIS) The full list of settings I have found is [here](https://github.com/incognitojam/op-notebooks/blob/main/ford/settings.py). * FwQueryConfig: add data_requests * add car_data to CarInterface get_params * Revert "add car_data to CarInterface get_params" This reverts commit aa161a6b82082705db97bea2c4317e1888a74845. * test_ford: add APIM ecu address * Revert "FwQueryConfig: add data_requests" This reverts commit dc5484a9b80be5bc61a7fdf55560b8813bc43ef7. * fix block numbers and add extra queries * bump test_fw_query_timing * add missing query whitelists * simplify asbuilt requests * use forscan block ids * formatting --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: c724d1c86ce4044bfc03f1e7941871466f51a708
1 year ago
Ecu.debug: 0x7D0, # Accessory Protocol Interface Module (APIM)
}
Ford: use platform codes to fuzzy fingerprint (#31124) * Ford: use platform codes to fuzzy fingerprint TODO: write scripts/tests (print platform codes and version ranges etc.) May close #31052 * get_platform_codes: fix return type * add print_platform_codes.py script * print_platform_codes: sort versions * match_fw_to_car_fuzzy: use set comprehension, and fix typo * Ford: add missing Mach-E fw From the route 83a4e056c7072678/2023-11-13--16-51-33 (which is already in selfdrive/car/tests/routes.py, added in #30691). * add ford_fuzzy_fingerprint.ipynb notebook * get_platform_codes: use regex to parse firmware * test_ford: test_platform_codes_fuzzy_fw * test_ford: use get_platform_codes in test_fw_versions * match_fw_to_car_fuzzy: improve comments * test_ford: add test_platform_codes_spot_check * test_ford: add test_match_fw_fuzzy * remove comment from notebook * TestFordFW: remove engine ECU FW * update print_platform_codes.py * remove part number (unecessary) * platform codes can just use platform hint and model year - software revision not useful * fuzzy FP on the platform hint and model year hint range * fix platform codes test * update notebook * add notebook * explain model year hint better * test part numbers again * cleanup notebooks * remove notebook * cleanup match_fw_to_car_fuzzy and add comments * update comment * . * Revert "remove notebook" This reverts commit 5d4ca202f2a23601d5c829204119f36a58f2b451. * add notebook back * remove PSCM from PLATFORM_CODE_ECUS ABS and IPMA are the best for uniquely matching, and the radar is always required * Revert "remove PSCM from PLATFORM_CODE_ECUS" This reverts commit b7baeac19c18b5aa0c31da52f12054f4bae6e1ff. * fix from merge * more fixes revert * FW_RE -> FW_PATTERN * this can actually be set * conventions * just add * convention * refactor matcher, this brings it more in line with Hyundai. IMPORTANT NOTE: NOTE THAT WE remove the separation for the different platform code model year hint ranges, I don't see that being a problem * better/smaller test * add test to catch overlapping platform codes * remove nb * not now --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: 85c9fea5d8e3f5ee673317e15df958a7168a899d
12 months ago
ECU_PART_NUMBER = {
Ecu.eps: [
b"14D003",
],
Ecu.abs: [
b"2D053",
],
Ecu.fwdRadar: [
b"14D049",
],
Ecu.fwdCamera: [
b"14F397", # Ford Q3
b"14H102", # Ford Q4
],
}
class TestFordFW(unittest.TestCase):
def test_fw_query_config(self):
for (ecu, addr, subaddr) in FW_QUERY_CONFIG.extra_ecus:
self.assertIn(ecu, ECU_ADDRESSES, "Unknown ECU")
self.assertEqual(addr, ECU_ADDRESSES[ecu], "ECU address mismatch")
self.assertIsNone(subaddr, "Unexpected ECU subaddress")
@parameterized.expand(FW_VERSIONS.items())
def test_fw_versions(self, car_model: str, fw_versions: dict[tuple[capnp.lib.capnp._EnumModule, int, int | None], Iterable[bytes]]):
for (ecu, addr, subaddr), fws in fw_versions.items():
Ford: use platform codes to fuzzy fingerprint (#31124) * Ford: use platform codes to fuzzy fingerprint TODO: write scripts/tests (print platform codes and version ranges etc.) May close #31052 * get_platform_codes: fix return type * add print_platform_codes.py script * print_platform_codes: sort versions * match_fw_to_car_fuzzy: use set comprehension, and fix typo * Ford: add missing Mach-E fw From the route 83a4e056c7072678/2023-11-13--16-51-33 (which is already in selfdrive/car/tests/routes.py, added in #30691). * add ford_fuzzy_fingerprint.ipynb notebook * get_platform_codes: use regex to parse firmware * test_ford: test_platform_codes_fuzzy_fw * test_ford: use get_platform_codes in test_fw_versions * match_fw_to_car_fuzzy: improve comments * test_ford: add test_platform_codes_spot_check * test_ford: add test_match_fw_fuzzy * remove comment from notebook * TestFordFW: remove engine ECU FW * update print_platform_codes.py * remove part number (unecessary) * platform codes can just use platform hint and model year - software revision not useful * fuzzy FP on the platform hint and model year hint range * fix platform codes test * update notebook * add notebook * explain model year hint better * test part numbers again * cleanup notebooks * remove notebook * cleanup match_fw_to_car_fuzzy and add comments * update comment * . * Revert "remove notebook" This reverts commit 5d4ca202f2a23601d5c829204119f36a58f2b451. * add notebook back * remove PSCM from PLATFORM_CODE_ECUS ABS and IPMA are the best for uniquely matching, and the radar is always required * Revert "remove PSCM from PLATFORM_CODE_ECUS" This reverts commit b7baeac19c18b5aa0c31da52f12054f4bae6e1ff. * fix from merge * more fixes revert * FW_RE -> FW_PATTERN * this can actually be set * conventions * just add * convention * refactor matcher, this brings it more in line with Hyundai. IMPORTANT NOTE: NOTE THAT WE remove the separation for the different platform code model year hint ranges, I don't see that being a problem * better/smaller test * add test to catch overlapping platform codes * remove nb * not now --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: 85c9fea5d8e3f5ee673317e15df958a7168a899d
12 months ago
self.assertIn(ecu, ECU_PART_NUMBER, "Unexpected ECU")
self.assertEqual(addr, ECU_ADDRESSES[ecu], "ECU address mismatch")
self.assertIsNone(subaddr, "Unexpected ECU subaddress")
for fw in fws:
self.assertEqual(len(fw), 24, "Expected ECU response to be 24 bytes")
Ford: use platform codes to fuzzy fingerprint (#31124) * Ford: use platform codes to fuzzy fingerprint TODO: write scripts/tests (print platform codes and version ranges etc.) May close #31052 * get_platform_codes: fix return type * add print_platform_codes.py script * print_platform_codes: sort versions * match_fw_to_car_fuzzy: use set comprehension, and fix typo * Ford: add missing Mach-E fw From the route 83a4e056c7072678/2023-11-13--16-51-33 (which is already in selfdrive/car/tests/routes.py, added in #30691). * add ford_fuzzy_fingerprint.ipynb notebook * get_platform_codes: use regex to parse firmware * test_ford: test_platform_codes_fuzzy_fw * test_ford: use get_platform_codes in test_fw_versions * match_fw_to_car_fuzzy: improve comments * test_ford: add test_platform_codes_spot_check * test_ford: add test_match_fw_fuzzy * remove comment from notebook * TestFordFW: remove engine ECU FW * update print_platform_codes.py * remove part number (unecessary) * platform codes can just use platform hint and model year - software revision not useful * fuzzy FP on the platform hint and model year hint range * fix platform codes test * update notebook * add notebook * explain model year hint better * test part numbers again * cleanup notebooks * remove notebook * cleanup match_fw_to_car_fuzzy and add comments * update comment * . * Revert "remove notebook" This reverts commit 5d4ca202f2a23601d5c829204119f36a58f2b451. * add notebook back * remove PSCM from PLATFORM_CODE_ECUS ABS and IPMA are the best for uniquely matching, and the radar is always required * Revert "remove PSCM from PLATFORM_CODE_ECUS" This reverts commit b7baeac19c18b5aa0c31da52f12054f4bae6e1ff. * fix from merge * more fixes revert * FW_RE -> FW_PATTERN * this can actually be set * conventions * just add * convention * refactor matcher, this brings it more in line with Hyundai. IMPORTANT NOTE: NOTE THAT WE remove the separation for the different platform code model year hint ranges, I don't see that being a problem * better/smaller test * add test to catch overlapping platform codes * remove nb * not now --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: 85c9fea5d8e3f5ee673317e15df958a7168a899d
12 months ago
match = FW_PATTERN.match(fw)
self.assertIsNotNone(match, f"Unable to parse FW: {fw!r}")
if match:
part_number = match.group("part_number")
self.assertIn(part_number, ECU_PART_NUMBER[ecu], f"Unexpected part number for {fw!r}")
codes = get_platform_codes([fw])
self.assertEqual(1, len(codes), f"Unable to parse FW: {fw!r}")
@settings(max_examples=100)
@given(data=st.data())
def test_platform_codes_fuzzy_fw(self, data):
"""Ensure function doesn't raise an exception"""
fw_strategy = st.lists(st.binary())
fws = data.draw(fw_strategy)
get_platform_codes(fws)
def test_platform_codes_spot_check(self):
# Asserts basic platform code parsing behavior for a few cases
results = get_platform_codes([
b"JX6A-14C204-BPL\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"NZ6T-14F397-AC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"PJ6T-14H102-ABJ\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"LB5A-14C204-EAC\x00\x00\x00\x00\x00\x00\x00\x00\x00",
])
self.assertEqual(results, {(b"X6A", b"J"), (b"Z6T", b"N"), (b"J6T", b"P"), (b"B5A", b"L")})
def test_fuzzy_match(self):
for platform, fw_by_addr in FW_VERSIONS.items():
# Ensure there's no overlaps in platform codes
for _ in range(20):
car_fw = []
for ecu, fw_versions in fw_by_addr.items():
ecu_name, addr, sub_addr = ecu
fw = random.choice(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), CP.carVin, FW_VERSIONS)
self.assertEqual(matches, {platform})
def test_match_fw_fuzzy(self):
offline_fw = {
(Ecu.eps, 0x730, None): [
b"L1MC-14D003-AJ\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"L1MC-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
],
(Ecu.abs, 0x760, None): [
b"L1MC-2D053-BA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"L1MC-2D053-BD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
],
(Ecu.fwdRadar, 0x764, None): [
b"LB5T-14D049-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"LB5T-14D049-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
],
# We consider all model year hints for ECU, even with different platform codes
(Ecu.fwdCamera, 0x706, None): [
b"LB5T-14F397-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
b"NC5T-14F397-AF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
],
}
expected_fingerprint = CAR.FORD_EXPLORER_MK6
# ensure that we fuzzy match on all non-exact FW with changed revisions
live_fw = {
(0x730, None): {b"L1MC-14D003-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
(0x760, None): {b"L1MC-2D053-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
(0x764, None): {b"LB5T-14D049-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
(0x706, None): {b"LB5T-14F397-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
}
candidates = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fw, '', {expected_fingerprint: offline_fw})
self.assertEqual(candidates, {expected_fingerprint})
# model year hint in between the range should match
live_fw[(0x706, None)] = {b"MB5T-14F397-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}
candidates = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fw, '', {expected_fingerprint: offline_fw,})
self.assertEqual(candidates, {expected_fingerprint})
Ford: use platform codes to fuzzy fingerprint (#31124) * Ford: use platform codes to fuzzy fingerprint TODO: write scripts/tests (print platform codes and version ranges etc.) May close #31052 * get_platform_codes: fix return type * add print_platform_codes.py script * print_platform_codes: sort versions * match_fw_to_car_fuzzy: use set comprehension, and fix typo * Ford: add missing Mach-E fw From the route 83a4e056c7072678/2023-11-13--16-51-33 (which is already in selfdrive/car/tests/routes.py, added in #30691). * add ford_fuzzy_fingerprint.ipynb notebook * get_platform_codes: use regex to parse firmware * test_ford: test_platform_codes_fuzzy_fw * test_ford: use get_platform_codes in test_fw_versions * match_fw_to_car_fuzzy: improve comments * test_ford: add test_platform_codes_spot_check * test_ford: add test_match_fw_fuzzy * remove comment from notebook * TestFordFW: remove engine ECU FW * update print_platform_codes.py * remove part number (unecessary) * platform codes can just use platform hint and model year - software revision not useful * fuzzy FP on the platform hint and model year hint range * fix platform codes test * update notebook * add notebook * explain model year hint better * test part numbers again * cleanup notebooks * remove notebook * cleanup match_fw_to_car_fuzzy and add comments * update comment * . * Revert "remove notebook" This reverts commit 5d4ca202f2a23601d5c829204119f36a58f2b451. * add notebook back * remove PSCM from PLATFORM_CODE_ECUS ABS and IPMA are the best for uniquely matching, and the radar is always required * Revert "remove PSCM from PLATFORM_CODE_ECUS" This reverts commit b7baeac19c18b5aa0c31da52f12054f4bae6e1ff. * fix from merge * more fixes revert * FW_RE -> FW_PATTERN * this can actually be set * conventions * just add * convention * refactor matcher, this brings it more in line with Hyundai. IMPORTANT NOTE: NOTE THAT WE remove the separation for the different platform code model year hint ranges, I don't see that being a problem * better/smaller test * add test to catch overlapping platform codes * remove nb * not now --------- Co-authored-by: Shane Smiskol <shane@smiskol.com> old-commit-hash: 85c9fea5d8e3f5ee673317e15df958a7168a899d
12 months ago
# unseen model year hint should not match
live_fw[(0x760, None)] = {b"M1MC-2D053-XX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}
candidates = FW_QUERY_CONFIG.match_fw_to_car_fuzzy(live_fw, '', {expected_fingerprint: offline_fw})
self.assertEqual(len(candidates), 0, "Should not match new model year hint")
if __name__ == "__main__":
unittest.main()