mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-18 13:33:53 +08:00
lunch time
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user