Add HKG EV App Start Climate wake

Add a StarPilot vehicle toggle that selects alternate Panda firmware for Hyundai/Kia/Genesis CAN-FD EVs. The firmware keeps the HKG CAN bus active while Panda is in power save and treats the app climate-active frame, bus 1 address 0x384 with byte 3 nonzero, as a Panda boot wake source without publishing it as CAN ignition.

Wire the toggle through StarPilot vehicle settings, Galaxy device settings, parameter definitions, and pandad firmware selection. Disabling the toggle selects the default Panda firmware again.

Tested on a Kia EV9 and 2023 Kia EV6. EV9 remote climate active used 0x384 byte 3 equal to 0x01; EV6 remote climate active used 0x0a. Both stopped/off states observed byte 3 equal to 0x00. Toggle-off negative testing on EV9 saw the remote climate frame on CAN but pandaStates.ignitionCan stayed false. Toggle-on testing verified the active Panda signature matched panda_h7_hkg_remote.bin.signed. Follow-up testing changed the HKG path to wake-only after remote climate caused partial-car fingerprinting and Dashcam Mode; wake-only firmware was built, flashed, and verified on both devices.
This commit is contained in:
firestar5683
2026-07-01 11:32:29 -05:00
parent 706c65a70d
commit 5234a121f9
15 changed files with 161 additions and 23 deletions
+1
View File
@@ -289,6 +289,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"FlashPanda", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"GMDashSpoofOffsets", {PERSISTENT, BOOL, "0", "0", 2}},
{"GMPedalLongitudinal", {PERSISTENT, BOOL, "1", "1", 2}},
{"HKGRemoteStartBootsComma", {PERSISTENT, BOOL, "0", "0"}},
{"IgnoreIgnitionLine", {PERSISTENT, BOOL, "0", "0"}},
{"LongPitch", {PERSISTENT, BOOL, "1", "0", 2}},
{"RemoteStartBootsComma", {PERSISTENT, BOOL, "0", "0"}},
+4
View File
@@ -169,10 +169,14 @@ build_project("panda", base_project_f4, "./board/main.c", [])
build_project("panda_h7", base_project_h7, "./board/main.c", [])
build_project("panda_remote", base_project_f4, "./board/main.c", ["-DPANDA_GM_REMOTE_START_C9"])
build_project("panda_h7_remote", base_project_h7, "./board/main.c", ["-DPANDA_GM_REMOTE_START_C9"])
build_project("panda_hkg_remote", base_project_f4, "./board/main.c", ["-DPANDA_HKG_REMOTE_START"])
build_project("panda_h7_hkg_remote", base_project_h7, "./board/main.c", ["-DPANDA_HKG_REMOTE_START"])
build_project("panda_can_ignition_only", base_project_f4, "./board/main.c", ["-DPANDA_IGNORE_IGNITION_LINE"])
build_project("panda_h7_can_ignition_only", base_project_h7, "./board/main.c", ["-DPANDA_IGNORE_IGNITION_LINE"])
build_project("panda_remote_can_ignition_only", base_project_f4, "./board/main.c", ["-DPANDA_GM_REMOTE_START_C9", "-DPANDA_IGNORE_IGNITION_LINE"])
build_project("panda_h7_remote_can_ignition_only", base_project_h7, "./board/main.c", ["-DPANDA_GM_REMOTE_START_C9", "-DPANDA_IGNORE_IGNITION_LINE"])
build_project("panda_hkg_remote_can_ignition_only", base_project_f4, "./board/main.c", ["-DPANDA_HKG_REMOTE_START", "-DPANDA_IGNORE_IGNITION_LINE"])
build_project("panda_h7_hkg_remote_can_ignition_only", base_project_h7, "./board/main.c", ["-DPANDA_HKG_REMOTE_START", "-DPANDA_IGNORE_IGNITION_LINE"])
# panda jungle fw
flags = [
+13 -2
View File
@@ -10,6 +10,10 @@ can_health_t can_health[PANDA_CAN_CNT] = {{0}, {0}, {0}};
// Ignition detected from CAN meessages
bool ignition_can = false;
uint32_t ignition_can_cnt = 0U;
#ifdef PANDA_HKG_REMOTE_START
bool hkg_remote_climate_wake = false;
uint32_t hkg_remote_climate_wake_cnt = 0U;
#endif
bool can_silent = true;
bool can_loopback = false;
@@ -161,9 +165,16 @@ void can_set_forwarding(uint8_t from, uint8_t to) {
#endif
void ignition_can_hook(CANPacket_t *msg) {
if (msg->bus == 0U) {
int len = GET_LEN(msg);
int len = GET_LEN(msg);
#ifdef PANDA_HKG_REMOTE_START
if ((msg->bus == 1U) && (msg->addr == 0x384U) && (len == 8)) {
hkg_remote_climate_wake = msg->data[3] != 0U;
hkg_remote_climate_wake_cnt = 0U;
}
#endif
if (msg->bus == 0U) {
// GM exception
// Remote-start mode uses 0xC9 bit 4 (SystemPowerMode=Run) for ignition detection.
// Stock mode uses 0x1F1 bit 1 (SystemPowerMode=Run/Crank Request).
+11
View File
@@ -189,6 +189,9 @@ static void tick_handler(void) {
// tick drivers at 1Hz
bool started = panda_ignition_line() || ignition_can;
#ifdef PANDA_HKG_REMOTE_START
started = started || hkg_remote_climate_wake;
#endif
bootkick_tick(started, recent_heartbeat);
// increase heartbeat counter and cap it at the uint32 limit
@@ -267,11 +270,19 @@ static void tick_handler(void) {
if (ignition_can_cnt > 2U) {
ignition_can = false;
}
#ifdef PANDA_HKG_REMOTE_START
if (hkg_remote_climate_wake_cnt > 2U) {
hkg_remote_climate_wake = false;
}
#endif
// on to the next one
uptime_cnt += 1U;
safety_mode_cnt += 1U;
ignition_can_cnt += 1U;
#ifdef PANDA_HKG_REMOTE_START
hkg_remote_climate_wake_cnt += 1U;
#endif
// synchronous safety check
safety_tick(&current_safety_config);
+8 -1
View File
@@ -9,7 +9,12 @@ void enable_can_transceivers(bool enabled) {
// Leave main CAN always on for CAN-based ignition detection
uint8_t main_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
for(uint8_t i=1U; i<=4U; i++){
current_board->enable_can_transceiver(i, (i == main_bus) || enabled);
bool transceiver_enabled = (i == main_bus) || enabled;
#ifdef PANDA_HKG_REMOTE_START
uint8_t hkg_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 4U : 2U;
transceiver_enabled = transceiver_enabled || (i == hkg_bus);
#endif
current_board->enable_can_transceiver(i, transceiver_enabled);
}
}
@@ -26,7 +31,9 @@ void set_power_save_state(int state) {
} else {
llcan_irq_disable(cans[2]);
}
#ifndef PANDA_HKG_REMOTE_START
llcan_irq_disable(cans[1]);
#endif
} else {
print("disable power savings\n");
+22 -12
View File
@@ -13,22 +13,24 @@ from openpilot.system.hardware import HARDWARE
from openpilot.common.swaglog import cloudlog
def get_selected_firmware_name(app_fn: str, remote_start: bool, ignore_ignition_line: bool) -> str:
if not remote_start and not ignore_ignition_line:
def get_selected_firmware_name(app_fn: str, remote_start: bool, hkg_remote_start: bool, ignore_ignition_line: bool) -> str:
if not remote_start and not hkg_remote_start and not ignore_ignition_line:
return app_fn
h7 = app_fn == "panda_h7.bin.signed"
name_parts = ["panda_h7" if h7 else "panda"]
if remote_start:
if hkg_remote_start:
name_parts.extend(["hkg", "remote"])
elif remote_start:
name_parts.append("remote")
if ignore_ignition_line:
name_parts.append("can_ignition_only")
return "_".join(name_parts) + ".bin.signed"
def get_expected_firmware_path(panda: Panda, remote_start: bool, ignore_ignition_line: bool) -> str:
def get_expected_firmware_path(panda: Panda, remote_start: bool, hkg_remote_start: bool, ignore_ignition_line: bool) -> str:
app_fn = panda.get_mcu_type().config.app_fn
selected_fn = get_selected_firmware_name(app_fn, remote_start, ignore_ignition_line)
selected_fn = get_selected_firmware_name(app_fn, remote_start, hkg_remote_start, ignore_ignition_line)
if selected_fn != app_fn:
selected_path = os.path.join(FW_PATH, selected_fn)
if os.path.isfile(selected_path):
@@ -37,9 +39,9 @@ def get_expected_firmware_path(panda: Panda, remote_start: bool, ignore_ignition
return os.path.join(FW_PATH, app_fn)
def get_expected_signature(panda: Panda, remote_start: bool, ignore_ignition_line: bool) -> bytes:
def get_expected_signature(panda: Panda, remote_start: bool, hkg_remote_start: bool, ignore_ignition_line: bool) -> bytes:
try:
fn = get_expected_firmware_path(panda, remote_start, ignore_ignition_line)
fn = get_expected_firmware_path(panda, remote_start, hkg_remote_start, ignore_ignition_line)
return Panda.get_signature_from_firmware(fn)
except Exception:
cloudlog.exception("Error computing expected signature")
@@ -53,6 +55,13 @@ def get_remote_start_boots_comma(params: Params) -> bool:
return False
def get_hkg_remote_start_boots_comma(params: Params) -> bool:
try:
return params.get_bool("HKGRemoteStartBootsComma")
except UnknownKeyName:
return False
def get_ignore_ignition_line(params: Params) -> bool:
try:
return params.get_bool("IgnoreIgnitionLine")
@@ -60,7 +69,7 @@ def get_ignore_ignition_line(params: Params) -> bool:
return False
def flash_panda(panda_serial: str, remote_start: bool, ignore_ignition_line: bool) -> Panda:
def flash_panda(panda_serial: str, remote_start: bool, hkg_remote_start: bool, ignore_ignition_line: bool) -> Panda:
try:
panda = Panda(panda_serial)
except PandaProtocolMismatch:
@@ -68,8 +77,8 @@ def flash_panda(panda_serial: str, remote_start: bool, ignore_ignition_line: boo
HARDWARE.recover_internal_panda()
raise
fw_path = get_expected_firmware_path(panda, remote_start, ignore_ignition_line)
fw_signature = get_expected_signature(panda, remote_start, ignore_ignition_line)
fw_path = get_expected_firmware_path(panda, remote_start, hkg_remote_start, ignore_ignition_line)
fw_signature = get_expected_signature(panda, remote_start, hkg_remote_start, ignore_ignition_line)
internal_panda = panda.is_internal()
panda_version = "bootstub" if panda.bootstub else panda.get_version()
@@ -153,9 +162,10 @@ def main() -> None:
# Flash pandas
pandas: list[Panda] = []
remote_start = get_remote_start_boots_comma(params)
hkg_remote_start = get_hkg_remote_start_boots_comma(params)
ignore_ignition_line = get_ignore_ignition_line(params)
for serial in panda_serials:
pandas.append(flash_panda(serial, remote_start, ignore_ignition_line))
pandas.append(flash_panda(serial, remote_start, hkg_remote_start, ignore_ignition_line))
# Ensure internal panda is present if expected
internal_pandas = [panda for panda in pandas if panda.is_internal()]
@@ -207,7 +217,7 @@ def main() -> None:
first_run = False
# run pandad with all connected serials as arguments
if get_remote_start_boots_comma(params) or get_ignore_ignition_line(params):
if get_remote_start_boots_comma(params) or get_hkg_remote_start_boots_comma(params) or get_ignore_ignition_line(params):
os.environ["BOARDD_SKIP_FW_CHECK"] = "1"
else:
os.environ.pop("BOARDD_SKIP_FW_CHECK", None)
@@ -209,6 +209,11 @@ class VehicleSettingsManagerView(PanelManagerView):
})
if cs.isHKGCanFd and cs.hasOpenpilotLongitudinal:
toggles.append({
"title": tr("EV Remote Climate"),
"get_state": lambda: self._controller._params.get_bool("HKGRemoteStartBootsComma"),
"set_state": lambda s: self._controller._on_panda_firmware_toggle("HKGRemoteStartBootsComma", tr("EV Remote Climate requires a Panda firmware update.")),
})
toggles.append({
"title": tr("Nostalgia Mode"),
"subtitle": tr("Use the left paddle to pause openpilot acceleration and braking."),
+10 -4
View File
@@ -173,13 +173,15 @@ def extract_zip(zip_file, extract_path):
print(f"Extraction completed!")
def get_selected_panda_firmware_name(app_fn, remote_start, ignore_ignition_line):
if not remote_start and not ignore_ignition_line:
def get_selected_panda_firmware_name(app_fn, remote_start, hkg_remote_start, ignore_ignition_line):
if not remote_start and not hkg_remote_start and not ignore_ignition_line:
return app_fn
h7 = app_fn == "panda_h7.bin.signed"
name_parts = ["panda_h7" if h7 else "panda"]
if remote_start:
if hkg_remote_start:
name_parts.extend(["hkg", "remote"])
elif remote_start:
name_parts.append("remote")
if ignore_ignition_line:
name_parts.append("can_ignition_only")
@@ -192,6 +194,10 @@ def flash_panda(params_memory):
remote_start = params.get_bool("RemoteStartBootsComma")
except Exception:
remote_start = False
try:
hkg_remote_start = params.get_bool("HKGRemoteStartBootsComma")
except Exception:
hkg_remote_start = False
try:
ignore_ignition_line = params.get_bool("IgnoreIgnitionLine")
except Exception:
@@ -203,7 +209,7 @@ def flash_panda(params_memory):
print(f"Flashing Panda {serial}")
flash_fn = None
app_fn = panda.get_mcu_type().config.app_fn
selected_fn = get_selected_panda_firmware_name(app_fn, remote_start, ignore_ignition_line)
selected_fn = get_selected_panda_firmware_name(app_fn, remote_start, hkg_remote_start, ignore_ignition_line)
if selected_fn != app_fn:
candidate = os.path.join(FW_PATH, selected_fn)
if os.path.isfile(candidate):
+4
View File
@@ -1392,6 +1392,10 @@ class StarPilotVariables:
condition=toggle.car_make == "gm" and toggle.has_pedal,
)
toggle.ignore_ignition_line = self.get_value("IgnoreIgnitionLine", condition=toggle.car_make == "gm")
toggle.hkg_remote_start_boots_comma = self.get_value(
"HKGRemoteStartBootsComma",
condition=toggle.car_make == "hyundai" and toggle.openpilot_longitudinal and bool(CP.flags & HyundaiFlags.CANFD),
)
toggle.long_pitch = self.get_value(
"LongPitch",
condition=toggle.openpilot_longitudinal and toggle.car_make == "gm",
@@ -13,6 +13,7 @@ const FAVORITE_OPTION_COLLATOR = new Intl.Collator(undefined, { numeric: true, s
let syncScheduled = false
let lastParams = null
const DYNAMIC_DEFAULT_DEP_KEYS = new Set(["AccelerationProfile", "EVTuning", "TruckTuning"])
const PANDA_FIRMWARE_TOGGLE_KEYS = new Set(["HKGRemoteStartBootsComma"])
// Module-level state (persists across route changes)
const state = reactive({
@@ -574,7 +575,13 @@ function updateFavoriteFilter(index, event) {
scheduleSyncInputs()
}
async function updateFavoriteValue(key, checked) {
async function updateFavoriteValue(key, checked, sourceEl = null) {
if (!confirmPandaFirmwareToggle(key, checked)) {
if (sourceEl) sourceEl.checked = !!state.values[key]
scheduleSyncInputs()
return
}
const current = state.values[key]
state.values = { ...state.values, [key]: checked }
state.favoriteValues = { ...state.favoriteValues, [key]: checked }
@@ -583,7 +590,7 @@ async function updateFavoriteValue(key, checked) {
const res = await fetch("/api/params", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ key, value: checked }),
body: JSON.stringify({ key, value: checked, ...pandaFirmwareConfirmationPayload(key) }),
})
const data = await res.json()
@@ -673,6 +680,25 @@ function showParamSnackbar(message, level, timeout = 2200) {
})
}
function getParamDisplayLabel(key) {
return state.paramMetaByKey[key]?.label || key
}
function confirmPandaFirmwareToggle(key, enabled) {
if (!PANDA_FIRMWARE_TOGGLE_KEYS.has(key)) return true
const label = getParamDisplayLabel(key)
const action = enabled ? "Enable" : "Disable"
return window.confirm(
`${label} requires a Panda firmware update.\n\n` +
`${action} ${label} and flash the Panda now?`
)
}
function pandaFirmwareConfirmationPayload(key) {
return PANDA_FIRMWARE_TOGGLE_KEYS.has(key) ? { confirmedPandaFirmwareFlash: true } : {}
}
function syncNumericDisplay(param, rawValue) {
const displayEl = document.getElementById(`ds-display-${param.key}`)
if (!displayEl) return
@@ -831,11 +857,16 @@ async function updateParam(key, elType) {
formattedVal = coerceValueByType(el.value, param.data_type)
}
if (elType === "checkbox" && !confirmPandaFirmwareToggle(key, formattedVal)) {
revertInput(key, current, elType)
return
}
try {
const res = await fetch("/api/params", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ key, value: formattedVal, label: selectedLabel }),
body: JSON.stringify({ key, value: formattedVal, label: selectedLabel, ...pandaFirmwareConfirmationPayload(key) }),
})
const data = await res.json()
@@ -1025,7 +1056,7 @@ function renderFavoriteSlotsPanel() {
class="ds-toggle ds-favorite-quick-toggle"
data-favorite-value-key="${selectedKey}"
checked="${() => selectedValue}"
@change="${(e) => updateFavoriteValue(selectedKey, !!e.currentTarget.checked)}" />
@change="${(e) => updateFavoriteValue(selectedKey, !!e.currentTarget.checked, e.currentTarget)}" />
</label>
`
})}
@@ -2520,6 +2520,13 @@
"data_type": "bool",
"ui_type": "toggle"
},
{
"key": "HKGRemoteStartBootsComma",
"label": "EV Remote Climate",
"description": "Use the remote-climate Hyundai/Kia/Genesis CAN-FD panda firmware at boot.\n\nRequired for EV remote-climate startup signal behavior.",
"data_type": "bool",
"ui_type": "toggle"
},
{
"key": "VoltSNG",
"label": "Stop-and-Go Hack",
+19
View File
@@ -113,6 +113,17 @@ _TESTING_GROUND_CUSTOM_RESERVED_INTERVAL_S = 15.0
_TESTING_GROUND_CUSTOM_RESERVED_PM = None
_TESTING_GROUND_CUSTOM_RESERVED_LOCK = threading.Lock()
_TESTING_GROUND_CUSTOM_RESERVED_LAST_PUBLISH_MONO = 0.0
PANDA_FIRMWARE_TOGGLE_KEYS = {"HKGRemoteStartBootsComma"}
PANDA_FIRMWARE_CONFIRMATION_FIELD = "confirmedPandaFirmwareFlash"
_PANDA_FLASH_REBOOT_LOCK = threading.Lock()
def _flash_panda_then_reboot() -> None:
with _PANDA_FLASH_REBOOT_LOCK:
params_memory.put_bool("FlashPanda", True)
while params_memory.get_bool("FlashPanda"):
time.sleep(0.1)
HARDWARE.reboot()
def _is_comma_device_runtime() -> bool:
@@ -3960,6 +3971,11 @@ def setup(app):
if key == "AutomaticUpdates" and params.get_bool("IsOnroad"):
return jsonify({"error": "Cannot change Automatic Updates while driving."}), 403
if key in PANDA_FIRMWARE_TOGGLE_KEYS and params.get_bool("IsOnroad"):
return jsonify({"error": "Cannot flash Panda firmware while driving."}), 403
if key in PANDA_FIRMWARE_TOGGLE_KEYS and data.get(PANDA_FIRMWARE_CONFIRMATION_FIELD) is not True:
return jsonify({"error": "Panda firmware changes require confirmation before flashing."}), 409
if key == "AllowImpossibleAcceleration":
enabled = str_val.strip() in ("1", "true", "True")
params.put_bool(key, enabled)
@@ -4186,6 +4202,9 @@ def setup(app):
response = {"message": f"Parameter '{key}' updated successfully."}
updated = {}
if key in PANDA_FIRMWARE_TOGGLE_KEYS:
threading.Thread(target=_flash_panda_then_reboot, daemon=True).start()
response["message"] = f"Parameter '{key}' updated successfully. Panda flashing started; device will reboot when finished."
if key == "RemapCancelToDistance" and params.get_bool("RemapCancelToDistance"):
updated["RemapCancelToDistance"] = True
response["message"] = "Remap Cancel Button enabled."
@@ -155,16 +155,19 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
settingsList->addItem(disableOpenpilotLong);
StarPilotListWidget *gmList = new StarPilotListWidget(this);
StarPilotListWidget *hkgList = new StarPilotListWidget(this);
StarPilotListWidget *subaruList = new StarPilotListWidget(this);
StarPilotListWidget *toyotaList = new StarPilotListWidget(this);
StarPilotListWidget *vehicleInfoList = new StarPilotListWidget(this);
ScrollView *gmPanel = new ScrollView(gmList, this);
ScrollView *hkgPanel = new ScrollView(hkgList, this);
ScrollView *subaruPanel = new ScrollView(subaruList, this);
ScrollView *toyotaPanel = new ScrollView(toyotaList, this);
ScrollView *vehicleInfoPanel = new ScrollView(vehicleInfoList, this);
vehiclesLayout->addWidget(gmPanel);
vehiclesLayout->addWidget(hkgPanel);
vehiclesLayout->addWidget(subaruPanel);
vehiclesLayout->addWidget(toyotaPanel);
vehiclesLayout->addWidget(vehicleInfoPanel);
@@ -179,6 +182,8 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
{"RemapCancelToDistance", tr("Remap Cancel Button"), tr("<b>On pedal-interceptor Bolts, treat the steering-wheel CANCEL button as an extra mappable button.</b>"), ""},
{"VoltSNG", tr("Stop-and-Go Hack"), tr("<b>Force stop-and-go</b> on the 2017 Chevy Volt."), ""},
{"HKGToggles", tr("Hyundai/Kia/Genesis Settings"), tr("<b>StarPilot features for Hyundai/Kia/Genesis vehicles.</b>"), ""},
{"HKGRemoteStartBootsComma", tr("EV Remote Climate"), tr("<b>Use the remote-climate Hyundai/Kia/Genesis CAN-FD panda firmware at boot.</b><br><br>Required for EV remote-climate startup signal behavior."), ""},
{"SubaruToggles", tr("Subaru Settings"), tr("<b>StarPilot features for Subaru vehicles.</b>"), ""},
{"SubaruSNG", tr("Stop and Go"), tr("Stop and go for supported Subaru vehicles."), ""},
@@ -212,6 +217,14 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
});
vehicleToggle = gmButton;
} else if (param == "HKGToggles") {
ButtonControl *hkgButton = new ButtonControl(title, tr("MANAGE"), desc);
QObject::connect(hkgButton, &ButtonControl::clicked, [vehiclesLayout, hkgPanel, this]() {
openDescriptions(forceOpenDescriptions, toggles);
vehiclesLayout->setCurrentWidget(hkgPanel);
});
vehicleToggle = hkgButton;
} else if (param == "SubaruToggles") {
ButtonControl *subaruButton = new ButtonControl(title, tr("MANAGE"), desc);
QObject::connect(subaruButton, &ButtonControl::clicked, [vehiclesLayout, subaruPanel, this]() {
@@ -264,6 +277,8 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
if (gmKeys.contains(param)) {
gmList->addItem(vehicleToggle);
} else if (hkgKeys.contains(param)) {
hkgList->addItem(vehicleToggle);
} else if (subaruKeys.contains(param)) {
subaruList->addItem(vehicleToggle);
} else if (toyotaKeys.contains(param)) {
@@ -322,6 +337,7 @@ StarPilotVehiclesPanel::StarPilotVehiclesPanel(StarPilotSettingsWindow *parent,
};
connectPandaFlashToggle("IgnoreIgnitionLine", tr("CAN Ignition Only requires a Panda firmware update. Flash the Panda now?"));
connectPandaFlashToggle("HKGRemoteStartBootsComma", tr("EV Remote Climate requires a Panda firmware update. Flash the Panda now?"));
connectPandaFlashToggle("RemoteStartBootsComma", tr("Remote Start requires a Panda firmware update. Flash the Panda now?"));
openDescriptions(forceOpenDescriptions, toggles);
@@ -393,6 +409,8 @@ void StarPilotVehiclesPanel::updateToggles() {
if (!showAllToggles) {
if (gmKeys.contains(key)) {
setVisible &= parent->isGM;
} else if (hkgKeys.contains(key)) {
setVisible &= parent->isHKGCanFd && parent->hasOpenpilotLongitudinal;
} else if (subaruKeys.contains(key)) {
setVisible &= parent->isSubaru;
} else if (toyotaKeys.contains(key)) {
@@ -439,6 +457,8 @@ void StarPilotVehiclesPanel::updateToggles() {
if (setVisible) {
if (gmKeys.contains(key)) {
toggles["GMToggles"]->setVisible(true);
} else if (hkgKeys.contains(key)) {
toggles["HKGToggles"]->setVisible(true);
} else if (subaruKeys.contains(key)) {
toggles["SubaruToggles"]->setVisible(true);
} else if (toyotaKeys.contains(key)) {
@@ -24,6 +24,7 @@ private:
std::map<QString, AbstractControl*> toggles;
QSet<QString> gmKeys = {"GMPedalLongitudinal", "GMDashSpoofOffsets", "IgnoreIgnitionLine", "LongPitch", "RemoteStartBootsComma", "RemapCancelToDistance", "VoltSNG"};
QSet<QString> hkgKeys = {"HKGRemoteStartBootsComma"};
QSet<QString> longitudinalKeys = {"FrogsGoMoosTweak", "GMDashSpoofOffsets", "LongPitch", "RemapCancelToDistance", "SNGHack", "VoltSNG"};
QSet<QString> subaruKeys = {"SubaruSNG", "SubaruSNGManualParkingBrake"};
QSet<QString> toyotaKeys = {"ClusterOffset", "FrogsGoMoosTweak", "LockDoorsTimer", "SNGHack", "ToyotaDoors"};
+1
View File
@@ -114,6 +114,7 @@ ForceTorqueController
FrogsGoMoosTweak
GMDashSpoofOffsets
GMPedalLongitudinal
HKGRemoteStartBootsComma
IgnoreIgnitionLine
GoatScream
GoatScreamCriticalAlerts