diff --git a/board/main.c b/board/main.c index 84e5da91..7d67119b 100644 --- a/board/main.c +++ b/board/main.c @@ -131,6 +131,7 @@ void set_safety_mode(uint16_t mode, uint16_t param) { bool is_car_safety_mode(uint16_t mode) { return (mode != SAFETY_SILENT) && (mode != SAFETY_NOOUTPUT) && + (mode != SAFETY_ALLOUTPUT) && (mode != SAFETY_ELM327); } @@ -192,6 +193,11 @@ void tick_handler(void) { heartbeat_counter += 1U; } + // disabling heartbeat not allowed while in safety mode + if (is_car_safety_mode(current_safety_mode)) { + heartbeat_disabled = false; + } + if (siren_countdown > 0U) { siren_countdown -= 1U; } diff --git a/board/main_comms.h b/board/main_comms.h index 0472f3e4..1f4914a8 100644 --- a/board/main_comms.h +++ b/board/main_comms.h @@ -531,12 +531,12 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) { case 0xf7: green_led_enabled = (req->param1 != 0U); break; -#ifdef ALLOW_DEBUG // **** 0xf8: disable heartbeat checks case 0xf8: - heartbeat_disabled = true; + if (!is_car_safety_mode(current_safety_mode)) { + heartbeat_disabled = true; + } break; -#endif // **** 0xde: set CAN FD data bitrate case 0xf9: if (req->param1 < CAN_CNT) { diff --git a/examples/query_fw_versions.py b/examples/query_fw_versions.py index 11aba600..2d450974 100755 --- a/examples/query_fw_versions.py +++ b/examples/query_fw_versions.py @@ -34,7 +34,6 @@ if __name__ == "__main__": panda = Panda() panda.set_safety_mode(Panda.SAFETY_ELM327) - panda.set_heartbeat_disabled() print("querying addresses ...") with tqdm(addrs) as t: for addr in t: diff --git a/python/__init__.py b/python/__init__.py index e12426d5..6458785b 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -209,7 +209,7 @@ class Panda: FLAG_GM_HW_CAM = 1 - def __init__(self, serial: Optional[str] = None, claim: bool = True): + def __init__(self, serial: Optional[str] = None, claim: bool = True, disable_checks: bool = True): self._serial = serial self._handle = None self._bcd_device = None @@ -217,6 +217,11 @@ class Panda: # connect and set mcu type self.connect(claim) + # disable openpilot's heartbeat checks + if disable_checks: + self.set_heartbeat_disabled() + self.set_power_save(0) + def close(self): self._handle.close() self._handle = None @@ -552,11 +557,8 @@ class Panda: self._handle.controlWrite(Panda.REQUEST_OUT, 0xda, int(bootmode), 0, b'') time.sleep(0.2) - def set_safety_mode(self, mode=SAFETY_SILENT, param=0, disable_checks=True): + def set_safety_mode(self, mode=SAFETY_SILENT, param=0): self._handle.controlWrite(Panda.REQUEST_OUT, 0xdc, mode, param, b'') - if disable_checks: - self.set_heartbeat_disabled() - self.set_power_save(0) def set_gmlan(self, bus=2): # TODO: check panda type diff --git a/tests/automated/2_health.py b/tests/automated/2_health.py index 5442d3a2..d77449af 100644 --- a/tests/automated/2_health.py +++ b/tests/automated/2_health.py @@ -61,3 +61,24 @@ def test_hw_type(p): assert pp.get_type() == hw_type, "Bootstub and app hw type mismatch" assert pp.get_mcu_type() == mcu_type, "Bootstub and app MCU type mismatch" pp.close() + + +@test_all_pandas +@panda_connect_and_init +def test_heartbeat(p): + # TODO: add more cases here once the tests aren't super slow + p.set_safety_mode(mode=Panda.SAFETY_HYUNDAI, param=Panda.FLAG_HYUNDAI_LONG) + p.send_heartbeat() + assert p.health()['safety_mode'] == Panda.SAFETY_HYUNDAI + assert p.health()['safety_param'] == Panda.FLAG_HYUNDAI_LONG + + # shouldn't do anything once we're in a car safety mode + p.set_heartbeat_disabled() + + time.sleep(6) + + h = p.health() + assert h['heartbeat_lost'] + assert h['safety_mode'] == Panda.SAFETY_SILENT + assert h['safety_param'] == 0 + assert h['controls_allowed'] == 0 diff --git a/tests/automated/helpers.py b/tests/automated/helpers.py index 7b612236..433a5122 100644 --- a/tests/automated/helpers.py +++ b/tests/automated/helpers.py @@ -197,7 +197,6 @@ def panda_connect_and_init(fn=None, full_reset=True): panda.set_can_speed_kbps(bus, speed) clear_can_buffers(panda) panda.set_power_save(False) - panda.set_heartbeat_disabled() try: fn(*pandas, *kwargs) diff --git a/tests/bulk_write_test.py b/tests/bulk_write_test.py index 5fcaca62..708258ba 100755 --- a/tests/bulk_write_test.py +++ b/tests/bulk_write_test.py @@ -33,7 +33,6 @@ if __name__ == "__main__": receiver.set_safety_mode(Panda.SAFETY_ALLOUTPUT) sender.set_safety_mode(Panda.SAFETY_ALLOUTPUT) - sender.set_heartbeat_disabled() # Start transmisson threading.Thread(target=flood_tx, args=(sender,)).start() diff --git a/tests/fan_test.py b/tests/fan_test.py index 9babf4fc..55657689 100755 --- a/tests/fan_test.py +++ b/tests/fan_test.py @@ -9,7 +9,6 @@ from panda import Panda # noqa: E402 power = 0 if __name__ == "__main__": p = Panda() - p.set_heartbeat_disabled() while True: p.set_fan_power(power) time.sleep(5) diff --git a/tests/message_drop_test.py b/tests/message_drop_test.py index d47edb00..c6991ce7 100755 --- a/tests/message_drop_test.py +++ b/tests/message_drop_test.py @@ -46,7 +46,6 @@ if __name__ == "__main__": receiver.set_safety_mode(Panda.SAFETY_ALLOUTPUT) sender.set_safety_mode(Panda.SAFETY_ALLOUTPUT) - sender.set_heartbeat_disabled() # Start transmisson threading.Thread(target=flood_tx, args=(sender,)).start()