fingerprint

This commit is contained in:
firestar5683
2026-09-15 14:01:39 -05:00
parent 0cf86c5c3b
commit dac7140410
3 changed files with 114 additions and 5 deletions
@@ -335,12 +335,31 @@ function scheduleSyncInputs() {
function applySelectOptions(el, options) {
el.innerHTML = ""
const labelsByValue = new Map()
for (const opt of options || []) {
if (opt?.developer_only && !state.values[GALAXY_DEVELOPER_MODE_KEY]) continue
const o = document.createElement("option")
o.value = String(opt.value)
o.textContent = opt.label
el.appendChild(o)
if (el.id === "ds-CarModel") {
if (!labelsByValue.has(o.value)) labelsByValue.set(o.value, [])
labelsByValue.get(o.value).push(o.textContent)
}
}
if (el.id === "ds-CarModel") {
for (const [modelValue, labels] of labelsByValue) {
if (labels.length < 2) continue
const baseNames = labels.map(label => label.split(" (")[0].replace(/\s+\d{4}.*$/, "").trim())
const baseName = baseNames.every(name => name === baseNames[0]) ? baseNames[0] : modelValue
const placeholder = document.createElement("option")
placeholder.value = modelValue
placeholder.textContent = `${baseName} (variant not identified)`
placeholder.dataset.fingerprintVariantPlaceholder = "1"
const firstVariant = Array.from(el.options).find(option => option.value === modelValue)
el.insertBefore(placeholder, firstVariant)
}
}
}
@@ -354,14 +373,16 @@ function syncSelectValue(el, key) {
if (key === "CarModel") {
const targetLabel = toSelectValue(state.values.CarModelName)
const options = Array.from(el.options)
const matchingIndex = options.findIndex(opt => {
if (opt.value !== targetValue) return false
return !targetLabel || opt.textContent === targetLabel
})
const matchingIndex = targetLabel ? options.findIndex(opt => opt.value === targetValue && opt.textContent === targetLabel) : -1
if (matchingIndex !== -1) {
el.selectedIndex = matchingIndex
return
}
const unspecifiedIndex = options.findIndex(opt => opt.value === targetValue && opt.dataset.fingerprintVariantPlaceholder === "1")
if (unspecifiedIndex !== -1) {
el.selectedIndex = unspecifiedIndex
return
}
}
el.value = targetValue
@@ -1,4 +1,5 @@
from test_dashboard_stats import MODULE_DIR, _install_server_import_stubs
from test_navigation_params import WritableFakeParams, _params_client, the_galaxy as api_server
def _load_server_module():
@@ -17,7 +18,68 @@ the_galaxy = _load_server_module()
def test_galaxy_lists_tesla_hardware_specific_docs_for_manual_fingerprinting():
tesla_models = the_galaxy._extract_fingerprint_models_for_make("tesla")
assert {"value": "TESLA_MODEL_S_PREAP", "label": "Tesla Model S (Pre-AP) 2012-14"} in tesla_models
assert {"value": "TESLA_MODEL_S_HW1", "label": "Tesla Model S (with HW1) 2014-16"} in tesla_models
assert {"value": "TESLA_MODEL_S_PREAP", "label": "Tesla Model S (with HW1) 2014-16"} not in tesla_models
assert {"value": "TESLA_MODEL_3", "label": "Tesla Model 3 (with HW3) 2019-23"} in tesla_models
assert {"value": "TESLA_MODEL_3", "label": "Tesla Model 3 (with HW4) 2024-26"} in tesla_models
assert {"value": "TESLA_MODEL_Y", "label": "Tesla Model Y (with HW3) 2020-23"} in tesla_models
assert {"value": "TESLA_MODEL_X", "label": "Tesla Model X (with HW4) 2024"} in tesla_models
catalog = the_galaxy._get_fingerprint_catalog()
assert catalog["label_to_model"]["Tesla Model S (with HW1) 2014-16"] == "TESLA_MODEL_S_HW1"
def test_galaxy_does_not_assign_a_regional_label_to_ambiguous_ev6_fingerprint():
kia_models = the_galaxy._extract_fingerprint_models_for_make("kia")
assert {"value": "KIA_EV6", "label": "Kia EV6 (Southeast Asia only) 2022-24"} in kia_models
assert {"value": "KIA_EV6", "label": "Kia EV6 (with HDA II) 2022-24"} in kia_models
catalog = the_galaxy._get_fingerprint_catalog()
assert catalog["model_to_label"]["KIA_EV6"] is None
def test_manual_fingerprint_api_keeps_the_saved_value_and_label_consistent(monkeypatch):
client, params = _params_client(monkeypatch, {}, "pc")
monkeypatch.setattr(api_server, "_get_param_type_info", lambda: ({"CarModel"}, {"CarModel": str}))
monkeypatch.setattr(api_server, "update_starpilot_toggles", lambda: None)
hw1_label = "Tesla Model S (with HW1) 2014-16"
options = client.get("/api/fingerprints/models?make=Tesla").get_json()
assert {"value": "TESLA_MODEL_S_HW1", "label": hw1_label} in options
response = client.put("/api/params", json={"key": "CarModel", "value": "TESLA_MODEL_S_HW1", "label": hw1_label})
assert response.status_code == 200
assert params.values["CarModel"] == "TESLA_MODEL_S_HW1"
assert params.values["CarModelName"] == hw1_label
response = client.put("/api/params", json={"key": "CarModel", "value": "TESLA_MODEL_S_PREAP", "label": hw1_label})
assert response.status_code == 400
assert params.values["CarModel"] == "TESLA_MODEL_S_HW1"
assert params.values["CarModelName"] == hw1_label
preap_label = "Tesla Model S (Pre-AP) 2012-14"
response = client.put("/api/params", json={"key": "CarModel", "value": "TESLA_MODEL_S_PREAP", "label": preap_label})
assert response.status_code == 200
assert params.values["CarModel"] == "TESLA_MODEL_S_PREAP"
assert params.values["CarModelName"] == preap_label
response = client.put("/api/params", json={"key": "CarModel", "value": "KIA_EV6"})
assert response.status_code == 200
assert params.values["CarModel"] == "KIA_EV6"
assert "CarModelName" not in params.values
hda_label = "Kia EV6 (with HDA II) 2022-24"
response = client.put("/api/params", json={"key": "CarModel", "value": "KIA_EV6", "label": hda_label})
assert response.status_code == 200
assert params.values["CarModelName"] == hda_label
def test_fingerprint_diagnostic_flags_a_stale_label_value_mismatch(monkeypatch):
monkeypatch.setattr(the_galaxy, "params", WritableFakeParams({
"CarModel": "TESLA_MODEL_S_PREAP",
"CarModelName": "Tesla Model S (with HW1) 2014-16",
}))
text = the_galaxy._get_fingerprint_snapshot_text()
assert "Mismatch" in text
assert "TESLA_MODEL_S_PREAP" in text
assert "reselect" in text.lower()
+27 -1
View File
@@ -13,6 +13,7 @@ import sysconfig
import tarfile
import io
import tokenize
from io import BytesIO
from pathlib import Path
@@ -3283,7 +3284,13 @@ def _extract_fingerprint_models_for_make(make_key):
except Exception:
return []
content = re.sub(r'#[^\n]*', "", content)
lines = content.splitlines(keepends=True)
for token in tokenize.generate_tokens(io.StringIO(content).readline):
if token.type == tokenize.COMMENT:
line_index, start = token.start[0] - 1, token.start[1]
end = token.end[1]
lines[line_index] = lines[line_index][:start] + " " * (end - start) + lines[line_index][end:]
content = "".join(lines)
content = re.sub(r'footnotes=\[[^\]]*\],\s*', "", content)
models = []
@@ -3327,6 +3334,7 @@ def _get_fingerprint_catalog():
all_models = []
seen_all = set()
model_to_label = {}
labels_by_model = {}
model_to_make = {}
label_to_model = {}
@@ -3340,6 +3348,7 @@ def _get_fingerprint_catalog():
model_label = entry["label"]
model_to_label.setdefault(model_value, model_label)
labels_by_model.setdefault(model_value, set()).add(model_label)
model_to_make.setdefault(model_value, make_label)
label_to_model.setdefault(model_label, model_value)
@@ -3356,6 +3365,10 @@ def _get_fingerprint_catalog():
all_models.sort(key=lambda entry: entry["label"].lower())
for model_value, labels in labels_by_model.items():
if len(labels) > 1:
model_to_label[model_value] = None
_fingerprint_catalog_cache = {
"makes": make_options,
"models_by_make": models_by_make,
@@ -4286,6 +4299,12 @@ def _get_fingerprint_snapshot_text():
model_value = str(params.get("CarModel", encoding="utf-8") or "").strip()
if model_name and model_value:
catalog = _get_fingerprint_catalog()
if model_value in catalog["model_to_make"] and not any(
entry["value"] == model_value and entry["label"] == model_name
for entry in catalog["all_models"]
):
return f"Mismatch: {model_name} vs {model_value}; reselect your vehicle"
return f"{model_name} ({model_value})"
if model_name:
return model_name
@@ -6588,6 +6607,13 @@ def setup(app):
return jsonify({"error": "Car model cannot be empty."}), 400
catalog = _get_fingerprint_catalog()
if selected_label_input:
labelled_models = {
entry["value"] for entry in catalog["all_models"]
if entry["label"] == selected_label_input
}
if labelled_models and selected_model not in labelled_models:
return jsonify({"error": "Vehicle label and model do not match; refresh and reselect your vehicle."}), 400
if selected_label_input and any(
entry["value"] == selected_model and entry["label"] == selected_label_input
for entry in catalog["all_models"]