Skip to content

Commit 168f2b9

Browse files
committed
Fix: Support VINs with no definite transmission
Some VINs might not include any information about the transmission. Using the example VINs from VIDA I couldn't find a VIN which did not specify at least the engine, so I'm still requiring that to be specified.
1 parent b1ac075 commit 168f2b9

File tree

4 files changed

+40
-21
lines changed

4 files changed

+40
-21
lines changed

.gitignore

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
sql/__pycache__/
1+
scripts/__pycache__/
2+
*.pyc
23
ecu/
34
csv/
45
images/
56
extracted_scripts/
6-
cache/
7+
cache/
8+
9+
# Python venv
10+
pyvenv.cfg
11+
bin/
12+
lib/
13+
include/
14+
15+
# OS stuff
16+
.DS_Store

scripts/read_csv.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def get_csv(csv_file: DatabaseFile) -> duckdb.DuckDBPyRelation:
4848
if csv_file in loaded_csv_dictionary:
4949
return loaded_csv_dictionary[csv_file]
5050
else:
51-
loaded_csv_dictionary[csv_file] = duckdb.read_csv(f'{root_directory}/csv/{csv_file}.csv', header=True, encoding='utf-8')
51+
loaded_csv_dictionary[csv_file] = duckdb.read_csv(f'{root_directory}/csv/{csv_file.value}.csv', header=True, encoding='utf-8')
5252
duckdb.register(csv_file.name, loaded_csv_dictionary[csv_file])
5353
return loaded_csv_dictionary[csv_file]
5454

scripts/vin_decoder.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def __init__(self, vin: str, row: pandas.Series):
2424
self.vehicle_model = row['fkVehicleModel']
2525
self.model_year = row['fkModelYear']
2626
self.partner_group = row['fkPartnerGroup']
27-
self.body_style = row['fkBodyStyle'] if row['fkBodyStyle'] != -1 else None
27+
self.body_style = row['fkBodyStyle'] if row['fkBodyStyle'] != -1 else 0
2828
self.engine = row['fkEngine']
2929
self.transmission = row['fkTransmission']
3030

@@ -40,7 +40,7 @@ def get_vehicle_profiles(self) -> list[str]:
4040
(fkPartnerGroup IS NULL OR fkPartnerGroup={self.partner_group}) AND
4141
(fkEngine IS NULL OR fkEngine={self.engine}) AND
4242
(fkTransmission IS NULL OR fkTransmission={self.transmission}) AND
43-
fkBodyStyle IS NULL AND
43+
(fkBodyStyle IS NULL OR fkBodyStyle={self.body_style}) AND
4444
fkSteering IS NULL AND
4545
fkNodeECU IS NULL AND
4646
fkSpecialVehicle IS NULL
@@ -49,7 +49,7 @@ def get_vehicle_profiles(self) -> list[str]:
4949

5050
def get_value_description(self, key: str) -> str:
5151
value = getattr(self, key)
52-
if value is None:
52+
if value is None or value == 0:
5353
return ""
5454

5555
# We use getattr here so the names from read_csv.DatabaseFile need to match up with our member variable names
@@ -112,29 +112,32 @@ def decode_vin(vin: str, partner_id: PartnerGroup = PartnerGroup.EUR, cached: bo
112112
get_csv(DatabaseFile.vehicle_profile)
113113

114114
# For cases where the VIN represents multiple combinations of engines and transmissions we match the table with itself to create
115-
# rows with every possible combination of engines and transmissions.
115+
# rows with every possible combination of engines and transmissions. However, we also want to allow VINs that only represent a single engine.
116116
combined = duckdb.sql("""
117117
SELECT DISTINCT c1.fkVehicleModel, c1.fkModelYear, c1.fkPartnerGroup, c1.fkBodyStyle, c1.fkEngine, c2.fkTransmission FROM components AS c1, components AS c2
118-
WHERE c1.fkEngine IS NOT NULL AND c2.fkTransmission IS NOT NULL
119-
""")
120-
121-
# Filter all the engine/transmission combinations for actually valid ones from the VehicleProfile table
122-
filtered = duckdb.sql("""
123-
SELECT DISTINCT combined.* FROM combined
124-
INNER JOIN vehicle_profile vp on vp.fkVehicleModel=combined.fkVehicleModel AND vp.fkModelYear=combined.fkModelYear
125-
WHERE combined.fkEngine=vp.fkEngine AND combined.fkTransmission=vp.fkTransmission
118+
WHERE (c1.fkEngine IS NOT NULL AND c2.fkTransmission IS NOT NULL) OR c1.fkEngine IS NOT NULL
126119
""").df()
127120

121+
# Filter all the engine/transmission combinations for actually valid ones from the VehicleProfile table if more than one exists
122+
if len(combined) > 1:
123+
filtered = duckdb.sql("""
124+
SELECT DISTINCT combined.* FROM combined
125+
INNER JOIN vehicle_profile vp on vp.fkVehicleModel=combined.fkVehicleModel AND vp.fkModelYear=combined.fkModelYear
126+
WHERE combined.fkEngine=vp.fkEngine AND combined.fkTransmission=vp.fkTransmission
127+
""").df()
128+
combined = filtered
129+
128130
# Replace possible NaN values with 'None' to avoid having float64 columns, and cast everything to int to not use numpy types
129-
filtered = filtered.replace({math.nan: -1}).astype('int64')
131+
combined = combined.replace({math.nan: 0}).astype('int64')
132+
print(combined)
130133

131-
if filtered.empty:
134+
if combined.empty:
132135
raise ValueError('Failed to find valid vehicle profiles for VIN')
133-
if len(filtered) > 1:
136+
if len(combined) > 1:
134137
raise ValueError('More than 1 vehicle profile appeared for VIN')
135138

136139
from vin_decoder import Vehicle
137-
vehicle = Vehicle(vin, filtered.loc[0])
140+
vehicle = Vehicle(vin, combined.loc[0])
138141
if cached:
139142
if not os.path.isdir("cache"):
140143
os.makedirs("cache")
@@ -145,5 +148,8 @@ def decode_vin(vin: str, partner_id: PartnerGroup = PartnerGroup.EUR, cached: bo
145148
if len(sys.argv) != 2:
146149
print('Usage: vin_decoder.py <VIN>')
147150
else:
148-
vehicle = decode_vin(sys.argv[1])
149-
vehicle.print()
151+
try:
152+
vehicle = decode_vin(sys.argv[1], cached=False)
153+
vehicle.print()
154+
except ValueError as e:
155+
print("Failed to decode VIN: " + str(e))

scripts/write_ecu_data.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Any, Generator
44
import sys
5+
import os
56
import pandas as pd
67

78
from read_csv import get_csvs, DatabaseFile, root_directory
@@ -34,6 +35,8 @@ def get_can_parameters_for_profiles(profile_identifiers: list[str]) -> Generator
3435
config = get_ecu_config(row['EcuVariantIdentifier']).df()
3536
ecu_configs.append(config)
3637

38+
os.mkdir(f'{root_directory}/ecu')
39+
3740
configs = pd.concat(ecu_configs, axis=0)
3841
print('Writing CAN config for ECUs...')
3942
configs.to_csv(f'{root_directory}/ecu/configs.csv', sep=',', encoding='utf-8')

0 commit comments

Comments
 (0)