94 lines
2.7 KiB
Python
94 lines
2.7 KiB
Python
"""
|
|
NHTSA VIN Decoder API client for the AUTOPARTES console application.
|
|
|
|
Wraps the National Highway Traffic Safety Administration (NHTSA) Vehicle
|
|
Product Information Catalog (vPIC) DecodeVin endpoint to retrieve vehicle
|
|
specifications from a 17-character VIN.
|
|
"""
|
|
|
|
import requests
|
|
|
|
from console.config import NHTSA_API_URL
|
|
|
|
|
|
# NHTSA result variables we care about, mapped to our internal keys.
|
|
_FIELD_MAP = {
|
|
"Make": "make",
|
|
"Model": "model",
|
|
"Model Year": "year",
|
|
"Body Class": "body_class",
|
|
"Drive Type": "drive_type",
|
|
"Displacement (L)": "displacement_l",
|
|
"Engine Number of Cylinders": "cylinders",
|
|
"Fuel Type - Primary": "fuel_type",
|
|
"Engine Brake (hp) From": "power_hp",
|
|
}
|
|
|
|
|
|
def decode_vin_nhtsa(vin: str) -> dict:
|
|
"""Decode a VIN using the NHTSA vPIC API.
|
|
|
|
Parameters
|
|
----------
|
|
vin : str
|
|
A 17-character Vehicle Identification Number.
|
|
|
|
Returns
|
|
-------
|
|
dict
|
|
On success::
|
|
|
|
{
|
|
"make": "TOYOTA",
|
|
"model": "Corolla",
|
|
"year": "2020",
|
|
"body_class": "Sedan/Saloon",
|
|
"drive_type": "FWD",
|
|
"engine_info": {
|
|
"displacement_l": "2.0",
|
|
"cylinders": "4",
|
|
"fuel_type": "Gasoline",
|
|
"power_hp": "169",
|
|
"raw": { ... full variable->value mapping ... },
|
|
},
|
|
}
|
|
|
|
On error::
|
|
|
|
{"error": "<description>"}
|
|
"""
|
|
try:
|
|
url = f"{NHTSA_API_URL}/{vin}"
|
|
response = requests.get(url, params={"format": "json"}, timeout=15)
|
|
response.raise_for_status()
|
|
|
|
data = response.json()
|
|
results = data.get("Results", [])
|
|
|
|
# Build a flat lookup: variable name -> value (skip empty/None)
|
|
raw: dict[str, str] = {}
|
|
for item in results:
|
|
var = item.get("Variable", "")
|
|
val = item.get("Value")
|
|
if val and str(val).strip():
|
|
raw[var] = str(val).strip()
|
|
|
|
# Extract top-level vehicle fields
|
|
vehicle: dict = {}
|
|
engine_info: dict = {"raw": raw}
|
|
|
|
engine_keys = {"displacement_l", "cylinders", "fuel_type", "power_hp"}
|
|
|
|
for nhtsa_var, our_key in _FIELD_MAP.items():
|
|
value = raw.get(nhtsa_var, "")
|
|
if our_key in engine_keys:
|
|
engine_info[our_key] = value
|
|
else:
|
|
vehicle[our_key] = value
|
|
|
|
vehicle["engine_info"] = engine_info
|
|
return vehicle
|
|
|
|
except Exception as e:
|
|
return {"error": str(e)}
|