mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-04 19:43:49 +08:00
Restore HKG coffee-break advisory replacements
This commit is contained in:
@@ -297,6 +297,7 @@ class CarController(CarControllerBase):
|
||||
self.frame += 1
|
||||
if _projection is not None:
|
||||
_projection.finish(new_actuators.torque)
|
||||
can_sends.extend(CS.daw.command(now_nanos))
|
||||
return new_actuators, can_sends
|
||||
|
||||
def create_can_msgs(self, apply_steer_req, apply_torque, torque_fault, set_speed_in_units, accel, stopping,
|
||||
|
||||
@@ -62,6 +62,8 @@ def get_non_scc_cruise_signals(flags: int, car=None) -> tuple[str, str, str, str
|
||||
class CarState(CarStateBase):
|
||||
def __init__(self, CP):
|
||||
super().__init__(CP)
|
||||
from opendbc.car.hyundai.daw import DawSource
|
||||
self.daw = DawSource(CP)
|
||||
self.forte_lkas_sources = NonSccLkasSources() if qualified_non_scc(CP) and CP.flags & HyundaiFlags.HAS_LDA_BUTTON else None
|
||||
if (qualified_classic_scc(CP) or qualified_classic_long(CP)) and CP.flags & HyundaiFlags.HAS_LDA_BUTTON:
|
||||
self.forte_lkas_sources = ClassicSccLkasSources(CP.carFingerprint)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
from opendbc.car import CanData
|
||||
from opendbc.car.hyundai.hyundaicanfd import CanBus, hkg_can_fd_checksum
|
||||
from opendbc.car.hyundai.values import CAR, HyundaiFlags, is_blended
|
||||
|
||||
|
||||
CANFD_DAW_WORDS = frozenset((0x11, 0x91, 0x811, 0x891, 0x8015, 0x8095, 0x8815, 0x8895))
|
||||
|
||||
|
||||
class DawSource:
|
||||
def __init__(self, cp):
|
||||
self.canfd = bool(cp.flags & HyundaiFlags.CANFD)
|
||||
self.enabled = (cp.brand == 'hyundai' and not cp.passive and not cp.dashcamOnly and not cp.notCar and
|
||||
not is_blended(cp) and (not self.canfd or cp.carFingerprint == CAR.HYUNDAI_IONIQ_6))
|
||||
if self.canfd:
|
||||
self.enabled = bool(self.enabled and cp.safetyConfigs and
|
||||
int(cp.safetyConfigs[-1].safetyParam) in CANFD_DAW_WORDS and CanBus(cp).ECAN % 4 == 1)
|
||||
self.address = 0x11A if self.canfd else 0x53E
|
||||
self.source_bus = CanBus(cp).ECAN if self.canfd else 2
|
||||
self.target_bus = CanBus(cp).ECAN if self.canfd else 0
|
||||
self.length = 16 if self.canfd else 6
|
||||
self.data = None
|
||||
self.stamp = 0
|
||||
|
||||
def update(self, packets):
|
||||
if not self.enabled:
|
||||
return
|
||||
for stamp, frames in packets:
|
||||
for address, data, bus in frames:
|
||||
if address != self.address or bus != self.source_bus:
|
||||
continue
|
||||
if stamp <= self.stamp or len(data) != self.length or (self.canfd and
|
||||
int.from_bytes(data[:2], 'little') != hkg_can_fd_checksum(address, None, data)):
|
||||
self.data = None
|
||||
continue
|
||||
self.data, self.stamp = bytes(data), stamp
|
||||
|
||||
def command(self, now_ns):
|
||||
if not self.enabled or self.data is None or not 0 < self.stamp <= now_ns <= self.stamp + 100_000_000:
|
||||
return []
|
||||
data = bytearray(self.data)
|
||||
if self.canfd:
|
||||
if (data[7] >> 3) & 7 == 1:
|
||||
data[7] &= ~0x38
|
||||
data[:2] = hkg_can_fd_checksum(self.address, None, data).to_bytes(2, 'little')
|
||||
elif 1 <= data[5] & 7 <= 3:
|
||||
data[5] &= ~7
|
||||
return [CanData(self.address, bytes(data), self.target_bus)]
|
||||
@@ -396,6 +396,9 @@ class CarInterface(CarInterfaceBase):
|
||||
return ret
|
||||
|
||||
def update(self, can_packets):
|
||||
if self.CS.daw.enabled:
|
||||
can_packets = list(can_packets)
|
||||
self.CS.daw.update(can_packets)
|
||||
recovery = getattr(getattr(self, 'CC', None), 'angle_tx_recovery', None)
|
||||
if recovery is not None:
|
||||
can_packets = list(can_packets)
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
import pytest
|
||||
|
||||
from opendbc.car import CanData, gen_empty_fingerprint, structs
|
||||
from opendbc.car.hyundai.daw import DawSource
|
||||
from opendbc.car.hyundai.hyundaicanfd import hkg_can_fd_checksum
|
||||
from opendbc.car.hyundai.interface import CarInterface
|
||||
from opendbc.car.hyundai.tests.test_ioniq6_stock_parser import params as ioniq6_params
|
||||
from opendbc.car.hyundai.values import CAR
|
||||
|
||||
BASE = 1_000_000_000
|
||||
|
||||
|
||||
def params(canfd):
|
||||
return ioniq6_params(True)[0] if canfd else CarInterface.get_params(
|
||||
CAR.HYUNDAI_SONATA_HYBRID, gen_empty_fingerprint(), [], False, False, False)
|
||||
|
||||
|
||||
def source(canfd, status):
|
||||
data = bytearray.fromhex('1234567898f8') if not canfd else bytearray(range(16))
|
||||
if canfd:
|
||||
data[7] = (data[7] & ~0x38) | (status << 3)
|
||||
data[:2] = hkg_can_fd_checksum(0x11A, None, data).to_bytes(2, 'little')
|
||||
else:
|
||||
data[5] = (data[5] & ~7) | status
|
||||
return bytes(data)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('canfd', (False, True))
|
||||
@pytest.mark.parametrize('status', range(8))
|
||||
def test_exact_current_advisory_only_transform(canfd, status):
|
||||
owner = DawSource(params(canfd))
|
||||
data = source(canfd, status)
|
||||
assert not owner.command(BASE)
|
||||
owner.update([(BASE, [CanData(owner.address, data, owner.source_bus)])])
|
||||
command, = owner.command(BASE)
|
||||
expected = bytearray(data)
|
||||
if canfd:
|
||||
if status == 1:
|
||||
expected[7] &= ~0x38
|
||||
expected[:2] = hkg_can_fd_checksum(owner.address, None, expected).to_bytes(2, 'little')
|
||||
elif 1 <= status <= 3:
|
||||
expected[5] &= ~7
|
||||
assert command == CanData(owner.address, bytes(expected), owner.target_bus)
|
||||
assert owner.data == data
|
||||
assert owner.command(BASE + 100_000_000)
|
||||
assert not owner.command(BASE + 100_000_001)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('canfd,fault', [(canfd, fault) for canfd in (False, True)
|
||||
for fault in ('future', 'old', 'reversed', 'length', 'returned', 'wrong_bus', 'wrong_address', 'crc')
|
||||
if canfd or fault != 'crc'])
|
||||
def test_bad_or_missing_sources_cannot_create_replacements(canfd, fault):
|
||||
owner = DawSource(params(canfd))
|
||||
data = source(canfd, 1)
|
||||
stamp, bus, addr = BASE, owner.source_bus, owner.address
|
||||
if fault == 'length':
|
||||
data = data[:-1]
|
||||
elif fault == 'returned':
|
||||
bus += 128
|
||||
elif fault == 'wrong_bus':
|
||||
bus = 0 if canfd else 1
|
||||
elif fault == 'wrong_address':
|
||||
addr += 1
|
||||
elif fault == 'crc':
|
||||
data = bytes([data[0] ^ 1]) + data[1:]
|
||||
elif fault == 'reversed':
|
||||
owner.update([(BASE + 1, [CanData(addr, data, bus)])])
|
||||
owner.update([(stamp, [CanData(addr, data, bus)])])
|
||||
now = BASE - 1 if fault == 'future' else BASE + 100_000_001 if fault == 'old' else BASE
|
||||
assert not owner.command(now)
|
||||
|
||||
|
||||
def test_actual_parser_and_controller_keep_optional_message_out_of_driving_health():
|
||||
cp = params(False)
|
||||
before = cp.to_dict()
|
||||
first, second = CarInterface(cp.as_reader().as_builder()), CarInterface(cp.as_reader().as_builder())
|
||||
data = bytes.fromhex('000000000883')
|
||||
plain = first.update([(BASE, [])])
|
||||
observed = second.update([(BASE, [CanData(0x53E, data, 2)])])
|
||||
assert observed.to_dict() == plain.to_dict()
|
||||
control = structs.CarControl()
|
||||
baseline = first.apply(control.as_reader(), BASE)[1]
|
||||
actual = second.apply(control.as_reader(), BASE)[1]
|
||||
assert [frame for frame in actual if frame[0] != 0x53E] == baseline
|
||||
assert [frame for frame in actual if frame[0] == 0x53E] == [CanData(0x53E, bytes.fromhex('000000000880'), 0)]
|
||||
assert cp.to_dict() == before
|
||||
|
||||
|
||||
def test_unrelated_canfd_profiles_do_not_emit_new_frames():
|
||||
cp = CarInterface.get_params(CAR.KIA_EV6, gen_empty_fingerprint(), [], False, False, False)
|
||||
owner = DawSource(cp)
|
||||
assert not owner.enabled
|
||||
owner.update([(BASE, [CanData(0x11A, source(True, 1), 1)])])
|
||||
assert not owner.command(BASE)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('word', (0, 1, 9, 0x15, 0x5491, 0x5495))
|
||||
def test_unsupported_ioniq6_native_profiles_cannot_emit_advisories(word):
|
||||
cp = params(True)
|
||||
cp.safetyConfigs[-1].safetyParam = word
|
||||
owner = DawSource(cp)
|
||||
assert not owner.enabled
|
||||
owner.update([(BASE, [CanData(0x11A, source(True, 1), owner.source_bus)])])
|
||||
assert not owner.command(BASE)
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "opendbc/safety/declarations.h"
|
||||
#include "opendbc/safety/modes/hyundai_common.h"
|
||||
#include "opendbc/safety/modes/hyundai_daw.h"
|
||||
#include "opendbc/safety/modes/hyundai_classic_non_scc_aol.h"
|
||||
#include "opendbc/safety/modes/hyundai_blended_stock_aol.h"
|
||||
|
||||
@@ -350,7 +351,7 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) {
|
||||
const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS_ALT = HYUNDAI_LIMITS(270, 2, 3);
|
||||
const TorqueSteeringLimits HYUNDAI_STEERING_LIMITS_ALT_2 = HYUNDAI_LIMITS(170, 2, 3);
|
||||
|
||||
bool tx = true;
|
||||
bool tx = (msg->addr != 0x53EU) || hyundai_daw_tx(msg);
|
||||
|
||||
if (hyundai_ray_pedal && (msg->addr == 0x200U)) {
|
||||
const uint16_t track1 = ((uint16_t)msg->data[0] << 8U) | msg->data[1];
|
||||
@@ -638,6 +639,7 @@ static safety_config hyundai_init(uint16_t param) {
|
||||
};
|
||||
|
||||
hyundai_common_init(param);
|
||||
hyundai_daw_init(false, false);
|
||||
if ((param == 0x800EU) && (alternative_experience == 0)) {
|
||||
hyundai_long_main_policy = HYUNDAI_MAIN_TRACK;
|
||||
}
|
||||
@@ -900,7 +902,7 @@ static safety_config hyundai_init(uint16_t param) {
|
||||
const safety_config denied = {0};
|
||||
ret = denied;
|
||||
}
|
||||
return ret;
|
||||
return hyundai_daw_configure(ret, false, !hyundai_blended_stock && !hyundai_blended_alpha);
|
||||
}
|
||||
|
||||
static safety_config hyundai_legacy_init(uint16_t param) {
|
||||
@@ -922,6 +924,7 @@ static safety_config hyundai_legacy_init(uint16_t param) {
|
||||
}
|
||||
}
|
||||
hyundai_common_init(normalized);
|
||||
hyundai_daw_init(false, false);
|
||||
classic_non_scc_aol_configure(normalized, !legacy_long);
|
||||
hyundai_legacy = true;
|
||||
hyundai_blended_stock = false;
|
||||
@@ -950,10 +953,11 @@ static safety_config hyundai_legacy_init(uint16_t param) {
|
||||
#endif
|
||||
}
|
||||
hyundai_classic_scc_aol_rx_config(&ret, true);
|
||||
return ret;
|
||||
return hyundai_daw_configure(ret, false, true);
|
||||
}
|
||||
|
||||
static void hyundai_optional_rx_hook(const CANPacket_t *msg) {
|
||||
hyundai_daw_rx(msg);
|
||||
if ((msg->addr == 0x391U) || (msg->addr == 0x50CU)) {
|
||||
blended_aol_rx(msg);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "opendbc/safety/declarations.h"
|
||||
#include "opendbc/safety/modes/hyundai_common.h"
|
||||
#include "opendbc/safety/modes/hyundai_daw.h"
|
||||
#include "opendbc/safety/modes/hyundai_canfd_aol.h"
|
||||
#include "opendbc/safety/modes/hyundai_canfd_angle_aol.h"
|
||||
|
||||
@@ -527,6 +528,7 @@ static void hyundai_canfd_ioniq6_optional_rx_hook(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
static void hyundai_canfd_optional_rx_hook(const CANPacket_t *msg) {
|
||||
hyundai_daw_rx(msg);
|
||||
if (hyundai_canfd_ioniq6_long && (msg->bus == 1U)) {
|
||||
hyundai_canfd_ioniq6_optional_rx_hook(msg);
|
||||
}
|
||||
@@ -1272,7 +1274,7 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
|
||||
}
|
||||
}
|
||||
if (ordinary_angle_valid && !((hyundai_canfd_ioniq6_long || hyundai_canfd_ccnc_ev_long) && safety_rx_checks_invalid)) {
|
||||
tx = hyundai_canfd_tx_hook_valid(msg);
|
||||
tx = (msg->addr == 0x11AU) ? hyundai_daw_tx(msg) : hyundai_canfd_tx_hook_valid(msg);
|
||||
}
|
||||
if ((hyundai_ordinary_angle_stock && !hyundai_angle_aol_enabled && (msg->addr == 0x110U) && tx) ||
|
||||
(independent_command && independent_active && tx)) {
|
||||
@@ -2221,6 +2223,7 @@ static safety_config hyundai_canfd_init_validated(uint16_t supplied_param) {
|
||||
}
|
||||
|
||||
static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
hyundai_daw_init(true, false);
|
||||
hyundai_canfd_reset_ioniq6_state();
|
||||
hyundai_ordinary_angle_reset();
|
||||
#ifdef ALLOW_DEBUG
|
||||
@@ -2239,6 +2242,9 @@ static safety_config hyundai_canfd_init(uint16_t param) {
|
||||
(param == 0x8815U) || (param == 0x8895U);
|
||||
if (valid && marker_valid) {
|
||||
ret = hyundai_canfd_init_validated(param);
|
||||
const bool daw_profile = (param == 0x0011U) || (param == 0x0091U) || (param == 0x0811U) || (param == 0x0891U) ||
|
||||
(param == 0x8015U) || (param == 0x8095U) || (param == 0x8815U) || (param == 0x8895U);
|
||||
ret = hyundai_daw_configure(ret, true, daw_profile);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include "opendbc/safety/modes/hyundai_common.h"
|
||||
|
||||
static uint16_t hyundai_daw_addr;
|
||||
static unsigned int hyundai_daw_bus;
|
||||
static unsigned int hyundai_daw_len;
|
||||
static uint8_t hyundai_daw_data[16];
|
||||
static uint8_t hyundai_daw_previous[16];
|
||||
static bool hyundai_daw_previous_seen;
|
||||
static uint32_t hyundai_daw_previous_ts;
|
||||
static uint32_t hyundai_daw_rx_ts;
|
||||
static uint32_t hyundai_daw_tx_ts;
|
||||
static bool hyundai_daw_seen;
|
||||
static bool hyundai_daw_counter_seen;
|
||||
static bool hyundai_daw_sent;
|
||||
|
||||
static void hyundai_daw_init(bool canfd, bool enabled) {
|
||||
hyundai_daw_addr = enabled ? (canfd ? 0x11AU : 0x53EU) : 0U;
|
||||
hyundai_daw_bus = canfd ? 1U : 0U;
|
||||
hyundai_daw_len = canfd ? 16U : 6U;
|
||||
hyundai_daw_previous_seen = false;
|
||||
hyundai_daw_previous_ts = 0U;
|
||||
hyundai_daw_seen = false;
|
||||
hyundai_daw_counter_seen = false;
|
||||
hyundai_daw_sent = false;
|
||||
hyundai_daw_rx_ts = 0U;
|
||||
hyundai_daw_tx_ts = 0U;
|
||||
}
|
||||
|
||||
static void hyundai_daw_rx(const CANPacket_t *msg) {
|
||||
const bool canfd = hyundai_daw_len == 16U;
|
||||
if ((hyundai_daw_addr != 0U) && (msg->addr == hyundai_daw_addr) && (msg->bus == (canfd ? hyundai_daw_bus : 2U))) {
|
||||
const uint32_t now = microsecond_timer_get();
|
||||
const bool fresh = hyundai_daw_counter_seen && (safety_get_ts_elapsed(now, hyundai_daw_rx_ts) <= 100000U);
|
||||
bool valid = GET_LEN(msg) == hyundai_daw_len;
|
||||
if (valid && canfd) {
|
||||
valid = GET_BYTES_LE(msg, 0, 2) == (hyundai_common_canfd_compute_checksum(msg) ^ 0x041DU);
|
||||
if (fresh) {
|
||||
valid &= (uint8_t)(msg->data[2] - hyundai_daw_data[2]) == 1U;
|
||||
}
|
||||
}
|
||||
hyundai_daw_previous_seen = canfd && valid && fresh && hyundai_daw_seen;
|
||||
if (hyundai_daw_previous_seen) {
|
||||
(void)memcpy(hyundai_daw_previous, hyundai_daw_data, hyundai_daw_len);
|
||||
hyundai_daw_previous_ts = hyundai_daw_rx_ts;
|
||||
}
|
||||
hyundai_daw_seen = valid;
|
||||
if (valid) {
|
||||
(void)memcpy(hyundai_daw_data, msg->data, hyundai_daw_len);
|
||||
hyundai_daw_rx_ts = now;
|
||||
hyundai_daw_counter_seen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t hyundai_daw_expected(const uint8_t *data, unsigned int i) {
|
||||
uint8_t expected = data[i];
|
||||
if ((hyundai_daw_len == 16U) && (i == 7U) && (((expected >> 3U) & 7U) == 1U)) {
|
||||
expected &= (uint8_t)~0x38U;
|
||||
} else if ((hyundai_daw_len == 6U) && (i == 5U) && ((expected & 7U) >= 1U) && ((expected & 7U) <= 3U)) {
|
||||
expected &= (uint8_t)~7U;
|
||||
} else {
|
||||
// Non-advisory payload bits are copied exactly from the current source.
|
||||
}
|
||||
return expected;
|
||||
}
|
||||
|
||||
static bool hyundai_daw_tx(const CANPacket_t *msg) {
|
||||
const uint32_t now = microsecond_timer_get();
|
||||
const bool canfd = hyundai_daw_len == 16U;
|
||||
bool valid = hyundai_daw_seen && (hyundai_daw_addr != 0U) && (msg->addr == hyundai_daw_addr) &&
|
||||
(msg->bus == hyundai_daw_bus) && (GET_LEN(msg) == hyundai_daw_len) &&
|
||||
(safety_get_ts_elapsed(now, hyundai_daw_rx_ts) <= 100000U) &&
|
||||
(!hyundai_daw_sent || (safety_get_ts_elapsed(now, hyundai_daw_tx_ts) >= 5000U));
|
||||
if (valid) {
|
||||
const uint8_t *source = hyundai_daw_data;
|
||||
if (canfd && (msg->data[2] != hyundai_daw_data[2])) {
|
||||
valid = hyundai_daw_previous_seen && (msg->data[2] == hyundai_daw_previous[2]) &&
|
||||
(safety_get_ts_elapsed(now, hyundai_daw_previous_ts) <= 100000U);
|
||||
if (valid) {
|
||||
// A one-frame receive race cannot replace newer warning or status data.
|
||||
for (unsigned int i = 3U; i < hyundai_daw_len; i++) {
|
||||
valid &= hyundai_daw_expected(hyundai_daw_previous, i) == hyundai_daw_expected(hyundai_daw_data, i);
|
||||
}
|
||||
source = hyundai_daw_previous;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = canfd ? 2U : 0U; i < hyundai_daw_len; i++) {
|
||||
valid &= msg->data[i] == hyundai_daw_expected(source, i);
|
||||
}
|
||||
if (canfd) {
|
||||
valid &= GET_BYTES_LE(msg, 0, 2) == (hyundai_common_canfd_compute_checksum(msg) ^ 0x041DU);
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
hyundai_daw_sent = true;
|
||||
hyundai_daw_tx_ts = now;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
static safety_config hyundai_daw_configure(safety_config ret, bool canfd, bool enabled) {
|
||||
hyundai_daw_init(canfd, false);
|
||||
if (enabled && (ret.tx_msgs_len > 0) && (ret.tx_msgs_len < 64)) {
|
||||
static CanMsg daw_tx_msgs[64];
|
||||
for (int i = 0; i < ret.tx_msgs_len; i++) {
|
||||
daw_tx_msgs[i] = ret.tx_msgs[i];
|
||||
}
|
||||
const CanMsg daw = {canfd ? 0x11AU : 0x53EU, canfd ? 1U : 0U, canfd ? 16U : 6U, .check_relay = false};
|
||||
daw_tx_msgs[ret.tx_msgs_len] = daw;
|
||||
ret.tx_msgs_len++;
|
||||
ret.tx_msgs = daw_tx_msgs;
|
||||
hyundai_daw_init(canfd, true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import pytest
|
||||
|
||||
from opendbc.car import structs
|
||||
from opendbc.car.hyundai.daw import DawSource
|
||||
from opendbc.car.hyundai.hyundaicanfd import hkg_can_fd_checksum
|
||||
from opendbc.car.hyundai.tests.test_daw import BASE, params, source
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
|
||||
|
||||
PROFILES = [(False, 0), (False, 0xC02), (True, 0x11), (True, 0x91), (True, 0x811), (True, 0x891),
|
||||
(True, 0x8015), (True, 0x8095), (True, 0x8815), (True, 0x8895)]
|
||||
|
||||
|
||||
def packet(addr, data, bus):
|
||||
return libsafety_py.make_CANPacket(addr, bus, data)
|
||||
|
||||
|
||||
def setup(canfd, word):
|
||||
safety = libsafety_py.libsafety
|
||||
debug = safety.set_safety_hooks(structs.CarParams.SafetyModel.allOutput, 0) == 0
|
||||
safety.set_alternative_experience(32 if word & 0x800 else 0)
|
||||
mode = structs.CarParams.SafetyModel.hyundaiCanfd if canfd else structs.CarParams.SafetyModel.hyundai
|
||||
assert safety.set_safety_hooks(mode, word) == 0
|
||||
safety.init_tests()
|
||||
safety.set_timer(1_000_000)
|
||||
return safety, debug or not (canfd and word & 0x8000)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('canfd,word', PROFILES)
|
||||
@pytest.mark.parametrize('status', range(8))
|
||||
def test_actual_host_commands_obey_native_source_payload_and_expiry(canfd, word, status):
|
||||
safety, supported = setup(canfd, word)
|
||||
owner = DawSource(params(canfd))
|
||||
data = source(canfd, status)
|
||||
owner.update([(BASE, [(owner.address, data, owner.source_bus)])])
|
||||
addr, output, bus = owner.command(BASE)[0]
|
||||
assert not safety.safety_tx_hook(packet(addr, output, bus))
|
||||
safety.safety_rx_hook(packet(addr, data, owner.source_bus))
|
||||
assert bool(safety.safety_tx_hook(packet(addr, output, bus))) == supported
|
||||
if not supported:
|
||||
return
|
||||
assert not safety.safety_tx_hook(packet(addr, output, bus))
|
||||
safety.set_timer(1_010_000)
|
||||
for bit in range(len(output) * 8):
|
||||
bad = bytearray(output)
|
||||
bad[bit // 8] ^= 1 << (bit % 8)
|
||||
assert not safety.safety_tx_hook(packet(addr, bad, bus)), bit
|
||||
assert safety.safety_tx_hook(packet(addr, output, bus))
|
||||
safety.set_timer(1_100_000)
|
||||
assert safety.safety_tx_hook(packet(addr, output, bus))
|
||||
safety.set_timer(1_100_001)
|
||||
assert not safety.safety_tx_hook(packet(addr, output, bus))
|
||||
assert not safety.get_controls_allowed()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('canfd,fault', [(canfd, fault) for canfd in (False, True)
|
||||
for fault in ('length', 'bus', 'crc', 'counter', 'reset', 'relay') if canfd or fault not in ('crc', 'counter')])
|
||||
def test_source_rejection_reset_and_relay_are_preserved(canfd, fault):
|
||||
safety, _ = setup(canfd, 0x11 if canfd else 0)
|
||||
owner = DawSource(params(canfd))
|
||||
data = source(canfd, 1)
|
||||
owner.update([(BASE, [(owner.address, data, owner.source_bus)])])
|
||||
addr, output, bus = owner.command(BASE)[0]
|
||||
incoming = data[:-4] if fault == 'length' and canfd else data[:-1] if fault == 'length' else data
|
||||
rx_bus = owner.source_bus + 1 if fault == 'bus' else owner.source_bus
|
||||
if fault == 'crc':
|
||||
incoming = bytes([incoming[0] ^ 1]) + incoming[1:]
|
||||
safety.safety_rx_hook(packet(addr, incoming, rx_bus))
|
||||
if fault == 'counter':
|
||||
safety.set_timer(1_010_000)
|
||||
safety.safety_rx_hook(packet(addr, incoming, rx_bus))
|
||||
elif fault == 'reset':
|
||||
setup(canfd, 0x11 if canfd else 0)
|
||||
elif fault == 'relay':
|
||||
safety.set_relay_malfunction(True)
|
||||
assert not safety.safety_tx_hook(packet(addr, output, bus))
|
||||
|
||||
|
||||
def test_forwarding_and_other_profiles_remain_unchanged():
|
||||
safety, _ = setup(False, 0)
|
||||
assert safety.safety_fwd_hook(2, 0x53E) == 0
|
||||
assert safety.safety_fwd_hook(0, 0x53E) == 2
|
||||
safety.set_safety_hooks(structs.CarParams.SafetyModel.hyundaiCanfd, 0)
|
||||
safety.init_tests()
|
||||
data = source(True, 1)
|
||||
safety.safety_rx_hook(packet(0x11A, data, 0))
|
||||
changed = bytearray(data)
|
||||
changed[7] &= ~0x38
|
||||
changed[:2] = hkg_can_fd_checksum(0x11A, None, changed).to_bytes(2, 'little')
|
||||
assert not safety.safety_tx_hook(packet(0x11A, changed, 0))
|
||||
|
||||
|
||||
def test_one_genuine_counter_predecessor_cannot_hide_newer_hands_off_request():
|
||||
safety, _ = setup(True, 0x11)
|
||||
owner = DawSource(params(True))
|
||||
data = source(True, 1)
|
||||
owner.update([(BASE, [(0x11A, data, 1)])])
|
||||
_, output, _ = owner.command(BASE)[0]
|
||||
safety.safety_rx_hook(packet(0x11A, data, 1))
|
||||
following = bytearray(data)
|
||||
following[2] += 1
|
||||
following[:2] = hkg_can_fd_checksum(0x11A, None, following).to_bytes(2, 'little')
|
||||
safety.set_timer(1_010_000)
|
||||
safety.safety_rx_hook(packet(0x11A, following, 1))
|
||||
assert safety.safety_tx_hook(packet(0x11A, output, 1))
|
||||
safety.set_timer(1_015_000)
|
||||
newer = bytearray(following)
|
||||
newer[2] += 1
|
||||
newer[:2] = hkg_can_fd_checksum(0x11A, None, newer).to_bytes(2, 'little')
|
||||
safety.safety_rx_hook(packet(0x11A, newer, 1))
|
||||
assert not safety.safety_tx_hook(packet(0x11A, output, 1))
|
||||
owner.update([(BASE + 10_000_000, [(0x11A, bytes(following), 1)])])
|
||||
_, prior_output, _ = owner.command(BASE + 10_000_000)[0]
|
||||
assert safety.safety_tx_hook(packet(0x11A, prior_output, 1))
|
||||
hands_off = bytearray(newer)
|
||||
hands_off[2] += 1
|
||||
hands_off[7] = (hands_off[7] & ~0x38) | (2 << 3)
|
||||
hands_off[:2] = hkg_can_fd_checksum(0x11A, None, hands_off).to_bytes(2, 'little')
|
||||
safety.set_timer(1_020_000)
|
||||
safety.safety_rx_hook(packet(0x11A, hands_off, 1))
|
||||
assert not safety.safety_tx_hook(packet(0x11A, prior_output, 1))
|
||||
owner.update([(BASE + 20_000_000, [(0x11A, bytes(newer), 1)])])
|
||||
_, prior_output, _ = owner.command(BASE + 20_000_000)[0]
|
||||
assert not safety.safety_tx_hook(packet(0x11A, prior_output, 1))
|
||||
owner.update([(BASE + 30_000_000, [(0x11A, bytes(hands_off), 1)])])
|
||||
_, current_output, _ = owner.command(BASE + 30_000_000)[0]
|
||||
assert safety.safety_tx_hook(packet(0x11A, current_output, 1))
|
||||
@@ -1 +0,0 @@
|
||||
{"protected_inventory_sha256": "fede7a3a054e8b7d37cc815a25f5d5296b19c34bc525281e97622bcbe1a569c0", "schema_version": 1}
|
||||
@@ -44,6 +44,7 @@ AOL_LIFECYCLE_TARGETS = (
|
||||
"opendbc_repo/opendbc/car/hyundai/tests/test_torque_ev_deferred_takeover.py",
|
||||
'openpilot/starpilot/aol/tests/test_hkg_early_long_withdrawal.py',
|
||||
'openpilot/starpilot/aol/tests/test_hkg_angle_eps_retention.py',
|
||||
'opendbc_repo/opendbc/car/hyundai/tests/test_daw.py',
|
||||
'openpilot/starpilot/aol/tests/test_hkg_angle_limit_warning.py',
|
||||
'openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock.py',
|
||||
'openpilot/starpilot/car/toyota/tests/test_prius_retrofit_stock_callers.py',
|
||||
@@ -513,6 +514,7 @@ RELEASE_TARGETS = (
|
||||
"opendbc_repo/opendbc/safety/tests/test_hyundai_ccnc_angle_two.py",
|
||||
"opendbc_repo/opendbc/safety/tests/test_hyundai_ioniq6_long.py",
|
||||
"opendbc_repo/opendbc/safety/tests/test_hyundai_ray_pedal.py",
|
||||
"opendbc_repo/opendbc/safety/tests/test_hyundai_daw.py",
|
||||
"opendbc_repo/opendbc/safety/tests/test_honda_mvl_stock.py",
|
||||
"opendbc_repo/opendbc/safety/tests/test_honda_stock_aol.py",
|
||||
"opendbc_repo/opendbc/safety/tests/test_mazda_stock_aol.py",
|
||||
|
||||
Reference in New Issue
Block a user