lunch time

This commit is contained in:
firestar5683
2026-09-15 13:05:50 -05:00
parent 814af739d0
commit d3ec77b0b4
6 changed files with 156 additions and 16 deletions
@@ -782,6 +782,7 @@ class CarController(CarControllerBase):
if blended_hda2:
can_sends.extend(hyundaicanfd.create_steering_messages(
self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, 0.0,
lka_icon=lka_icon,
longitudinal_active=longitudinal_active,
))
if self.long_active_ecu:
@@ -792,6 +793,7 @@ class CarController(CarControllerBase):
left_lane_warning, right_lane_warning, CS.msg_364,
include_alerts=False,
counter_mod=0xF,
fcw_opt_usm=2 if apply_steer_req or lka_icon == 3 else 1,
))
if self.frame % 5 == 0:
can_sends.append(hyundaicanfd.create_suppress_lfa(
@@ -129,13 +129,13 @@ def create_lkas11_can_canfd_blended(packer, frame, CP, apply_steer, steer_req,
torque_fault, lkas11, sys_warning, sys_state, enabled,
left_lane, right_lane,
left_lane_depart, right_lane_depart, msg_364,
include_alerts=True, counter_mod=0x10):
include_alerts=True, counter_mod=0x10, fcw_opt_usm=None):
bus = CanBus(CP).ECAN
values = {
"CF_Lkas_LdwsActivemode": int(left_lane) + (int(right_lane) << 1),
"CF_Lkas_LdwsLHWarning": left_lane_depart,
"CF_Lkas_LdwsRHWarning": right_lane_depart,
"CF_Lkas_FcwOpt_USM": 2 if enabled else 1,
"CF_Lkas_FcwOpt_USM": (2 if enabled else 1) if fcw_opt_usm is None else fcw_opt_usm,
"CR_Lkas_StrToqReq": apply_steer,
"CF_Lkas_ActToi": steer_req,
"CF_Lkas_ToiFlt": torque_fault,
@@ -727,6 +727,45 @@ class TestHyundaiFingerprint:
} <= msg_addrs_buses
assert (0x364, 1) not in msg_addrs_buses
def test_palisade_telluride_hda2_aol_keeps_lkas_status_after_long_cancel(self):
fingerprint = gen_empty_fingerprint()
fingerprint[2][0x50] = 16
car_fw = [CarParams.CarFw(ecu=Ecu.adas, fwVersion=b"", address=0x730, brand="hyundai")]
CP = CarInterface.get_params(CAR.HYUNDAI_PALISADE_2023, fingerprint, car_fw, True, False, False, None)
controller = CarController(DBC[CP.carFingerprint], CP)
controller.frame = 1
hud_control = SimpleNamespace(
visualAlert=CarControl.HUDControl.VisualAlert.none,
leftLaneVisible=True,
rightLaneVisible=True,
leftLaneDepart=False,
rightLaneDepart=False,
leadDistanceBars=3,
leadVisible=False,
)
lfa_block_msg = {f"BYTE{i}": 0 for i in range(3, 24) if i != 7}
lfa_block_msg["COUNTER"] = 0
CS = SimpleNamespace(lfa_block_msg=lfa_block_msg, redneck_send_button=Buttons.NONE, lkas11={}, msg_364={},
out=SimpleNamespace(vEgoRaw=5.0))
CC = SimpleNamespace(enabled=False, latActive=True, longActive=False,
cruiseControl=SimpleNamespace(cancel=False, resume=False, override=False))
actuators = SimpleNamespace(longControlState=LongCtrlState.off)
adas_parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS", 0)], 0)
ecan_parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LKAS11", 0)], 1)
for steering_requested, icon, expected_status in ((True, 2, 2), (False, 1, 1)):
msgs = controller.create_can_msgs(steering_requested, 16 if steering_requested else 0, False,
0.0, 0.0, False, hud_control, actuators, CS, CC, icon, icon)
adas_parser.update([(1, [msg for msg in msgs if msg[0] == 0x50])])
ecan_parser.update([(1, [msg for msg in msgs if msg[0] == 0x340])])
assert adas_parser.vl["LKAS"]["LKA_ICON"] == icon
assert adas_parser.vl["LKAS"]["STEER_REQ"] == int(steering_requested)
assert ecan_parser.vl["LKAS11"]["CF_Lkas_FcwOpt_USM"] == expected_status
assert ecan_parser.vl["LKAS11"]["CF_Lkas_ActToi"] == int(steering_requested)
assert not any(msg[0] == 0x364 for msg in msgs)
def test_g70_aol_uses_active_lkas_icon(self):
CP = CarInterface.get_params(CAR.GENESIS_G70_2020, gen_empty_fingerprint(), [], False, False, False, None)
controller = CarController(DBC[CP.carFingerprint], CP)
@@ -1833,6 +1833,69 @@ button.gx-chip:hover {
margin-top: var(--sp-5);
}
.gx-sentry-images {
display: flex;
flex-wrap: wrap;
gap: var(--sp-2);
}
.gx-sentry-image-button {
background: transparent;
border: 0;
border-radius: var(--radius-sm);
cursor: zoom-in;
flex: 1 1 45%;
min-width: 120px;
padding: 0;
}
.gx-sentry-image-button img {
border-radius: var(--radius-sm);
display: block;
width: 100%;
}
.gx-sentry-image-button:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 3px;
}
.gx-scrim--image-viewer {
padding: var(--sp-3);
}
.gx-image-viewer {
display: flex;
flex-direction: column;
max-height: calc(100dvh - var(--sp-6));
max-width: min(960px, 100%);
padding: var(--sp-3);
}
.gx-image-viewer__header {
align-items: center;
display: flex;
gap: var(--sp-2);
justify-content: space-between;
margin-bottom: var(--sp-3);
}
.gx-image-viewer__header .gx-sheet__title {
margin: 0;
min-width: 0;
overflow-wrap: anywhere;
}
.gx-image-viewer__image {
border-radius: var(--radius-sm);
display: block;
height: auto;
margin: auto;
max-height: calc(100dvh - 120px);
max-width: 100%;
object-fit: contain;
}
/* Native-style bottom sheet used for fullscreen player overlays. Kept as a
sibling of gx-sheet so confirm dialogs keep their centered look. */
.gx-scrim--bottomsheet {
@@ -28,14 +28,24 @@ export const Sentry = {
liveBusy: false,
deleteBusy: false,
pushBusy: false,
selectedImage: null,
}
},
created() {
this.poll = usePolling(() => this.loadStatus(), { interval: 5000 })
this.poll.start()
},
mounted() { this.loadParams() },
beforeUnmount() { this.poll?.destroy() },
mounted() {
this.loadParams()
this._onKeydown = (event) => {
if (event.key === "Escape" && this.selectedImage) this.closeImage()
}
window.addEventListener("keydown", this._onKeydown)
},
beforeUnmount() {
this.poll?.destroy()
window.removeEventListener("keydown", this._onKeydown)
},
computed: {
statusText() { return String(this.status?.state || "unknown") },
hasEvent() { return !!(this.event && this.event.eventId) },
@@ -129,6 +139,13 @@ export const Sentry = {
const cacheKey = encodeURIComponent(this.liveCapture?.capturedAt || "")
return cacheKey ? `${url}?t=${cacheKey}` : url
},
openImage(src, alt) {
if (!src) return
this.selectedImage = { src: String(src), alt: String(alt || "Sentry capture") }
},
closeImage() {
this.selectedImage = null
},
async enablePush() {
if (this.pushBusy) return
this.pushBusy = true
@@ -309,10 +326,11 @@ export const Sentry = {
</div>
<template v-if="Array.isArray(liveCapture.imageUrls) && liveCapture.imageUrls.length">
<p class="gx-row__desc">Captured {{ liveCapture.capturedAt || 'just now' }}.</p>
<div style="display:flex; flex-wrap:wrap; gap:8px;">
<a v-for="(u, i) in liveCapture.imageUrls" :key="u + i" :href="liveImageUrl(u)" target="_blank" rel="noopener" style="flex:1 1 45%; min-width:120px;">
<img :src="liveImageUrl(u)" :alt="'Live Sentry camera ' + (i + 1)" style="width:100%; border-radius:8px; display:block;" />
</a>
<div class="gx-sentry-images">
<button v-for="(u, i) in liveCapture.imageUrls" :key="u + i" type="button" class="gx-sentry-image-button"
:aria-label="'Open Live Sentry camera ' + (i + 1)" @click="openImage(liveImageUrl(u), 'Live Sentry camera ' + (i + 1))">
<img :src="liveImageUrl(u)" :alt="'Live Sentry camera ' + (i + 1)" />
</button>
</div>
</template>
<p v-else class="gx-empty">No live snapshot captured yet.</p>
@@ -341,10 +359,11 @@ export const Sentry = {
</div>
<p style="margin:8px 0;"><strong>{{ event.message || 'Movement detected while parked.' }}</strong></p>
<template v-if="Array.isArray(event.imageUrls) && event.imageUrls.length">
<div style="display:flex; flex-wrap:wrap; gap:8px;">
<a v-for="(u, i) in event.imageUrls" :key="u + i" :href="u" target="_blank" rel="noopener" style="flex:1 1 45%; min-width:120px;">
<img :src="u" :alt="'Sentry capture ' + (i + 1)" loading="lazy" style="width:100%; border-radius:8px; display:block;" />
</a>
<div class="gx-sentry-images">
<button v-for="(u, i) in event.imageUrls" :key="u + i" type="button" class="gx-sentry-image-button"
:aria-label="'Open Sentry capture ' + (i + 1)" @click="openImage(u, 'Sentry capture ' + (i + 1))">
<img :src="u" :alt="'Sentry capture ' + (i + 1)" loading="lazy" />
</button>
</div>
</template>
<p v-else-if="event.kind === 'power_off'" class="gx-empty">Power-off alerts do not include camera captures because the device is shutting down.</p>
@@ -368,10 +387,11 @@ export const Sentry = {
</div>
<p style="margin:8px 0;"><strong>{{ ev.message || 'Movement detected while parked.' }}</strong></p>
<template v-if="Array.isArray(ev.imageUrls) && ev.imageUrls.length">
<div style="display:flex; flex-wrap:wrap; gap:8px;">
<a v-for="(u, i) in ev.imageUrls" :key="u + i" :href="u" target="_blank" rel="noopener" style="flex:1 1 45%; min-width:120px;">
<img :src="u" :alt="'Sentry capture ' + (i + 1)" loading="lazy" style="width:100%; border-radius:8px; display:block;" />
</a>
<div class="gx-sentry-images">
<button v-for="(u, i) in ev.imageUrls" :key="u + i" type="button" class="gx-sentry-image-button"
:aria-label="'Open Sentry capture ' + (i + 1)" @click="openImage(u, 'Sentry capture ' + (i + 1))">
<img :src="u" :alt="'Sentry capture ' + (i + 1)" loading="lazy" />
</button>
</div>
</template>
<p v-else class="gx-empty">No camera images were available for this event.</p>
@@ -381,6 +401,18 @@ export const Sentry = {
</div>
</div>
</GalaxySection>
<div v-if="selectedImage" class="gx-scrim gx-scrim--image-viewer" @click.self="closeImage">
<div class="gx-sheet gx-image-viewer" role="dialog" aria-modal="true" :aria-label="selectedImage.alt">
<div class="gx-image-viewer__header">
<span class="gx-sheet__title">{{ selectedImage.alt }}</span>
<button type="button" class="gx-icon-btn" aria-label="Close image" title="Close image" @click="closeImage">
<i class="bi bi-x-lg" aria-hidden="true"></i>
</button>
</div>
<img class="gx-image-viewer__image" :src="selectedImage.src" :alt="selectedImage.alt" />
</div>
</div>
</div>
`,
}
@@ -489,6 +489,10 @@ def test_ui_all_remaining_classic_tools_native_no_embed():
assert '"/sentry": Cameras' in app
sentry = _read("js/views/Sentry.js")
assert "GalaxyEmbed" not in sentry and "fetch(" not in sentry
assert "selectedImage" in sentry and "openImage" in sentry and "closeImage" in sentry
assert 'class="gx-scrim gx-scrim--image-viewer"' in sentry
assert 'aria-label="Close image"' in sentry
assert 'target="_blank"' not in sentry
# Navigation maps + App Keys and Tuning lateral are native tabs now.
nav = _read("js/views/Navigation.js")