Watch
0
0
Fork
You've already forked esp32-c_its-companion
0

WIP screen: Show min and max end time

TODO: only on big screen!?
This commit is contained in:
Jannik Beyerstedt 2026-08-15 14:17:52 +02:00
commit f2960f36af
4 changed files with 126 additions and 35 deletions

View file

@ -106,7 +106,54 @@ pub struct GlosaSignalInfo {
pub struct SignalGroupData {
pub phase: SignalPhase,
pub maneuver: map::Maneuvers,
pub end_sec: Option<i16>,
pub timing: Option<TimingData>,
}
#[cfg(feature = "spat")]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct TimingData {
pub min_end_sec: i16,
pub likely_end_sec: Option<i16>,
pub max_end_sec: Option<i16>,
}
impl TimingData {
pub fn new(value: &map::SignalGroup, now: chrono::DateTime<chrono::Utc>) -> Option<Self> {
let min = value
.min_end_time()
.map(|val| Self::time_to_duration_sec(now, val));
let likely_end_sec = value
.likely_time()
.map(|val| Self::time_to_duration_sec(now, val));
let max_end_sec = value
.min_end_time()
.map(|val| Self::time_to_duration_sec(now, val));
if let Some(min_end_sec) = min {
Some(Self {
min_end_sec,
likely_end_sec,
max_end_sec,
})
} else {
None
}
}
fn time_to_duration_sec(
now: chrono::DateTime<chrono::Utc>,
time_point: chrono::DateTime<chrono::Utc>,
) -> i16 {
use core::ops::Sub as _;
use num_traits::Float as _;
let dur = time_point.sub(now).as_seconds_f32();
#[allow(clippy::cast_possible_truncation)]
let duration_sec = dur.round() as i16;
duration_sec
}
}
#[cfg(feature = "spat")]
@ -357,33 +404,17 @@ impl State {
let sig_grps = approach_sig_grps
.iter()
.filter_map(|sig| {
if let Some(manv) = sig.maneuvers() {
use core::ops::Sub;
use num_traits::Float;
if let Some(maneuver) = sig.maneuvers() {
let phase = sig
.phase()
.map(core::convert::Into::into)
.unwrap_or_default();
let end_sec = sig
.likely_time()
.or_else(|| sig.min_end_time())
.map(|time| {
let dur =
time.sub(self.time.and_utc()).as_seconds_f32();
#[allow(clippy::cast_possible_truncation)]
let end_sec = dur.round() as i16;
end_sec
});
let timing = TimingData::new(*sig, self.time.and_utc());
Some(SignalGroupData {
phase,
maneuver: manv,
end_sec,
maneuver,
timing,
})
} else {
None

View file

@ -173,6 +173,12 @@ impl Intersection {
{
sig_grp.likely_time = Some(likely.to_datetime_from_moy(moy, year));
}
if let Some(max) = &timing.max_end_time
&& !max.is_out_of_range()
&& !max.is_unknown()
{
sig_grp.max_end_time = Some(max.to_datetime_from_moy(moy, year));
}
}
}
} else {
@ -223,6 +229,7 @@ impl Intersection {
target_lanes,
phase: None,
min_end_time: None,
max_end_time: None,
likely_time: None,
}
})
@ -410,7 +417,7 @@ pub struct SignalGroup {
/// current signal phase
phase: Option<etsi_its_dsrc::MovementPhaseState>,
min_end_time: Option<chrono::DateTime<chrono::Utc>>,
// max_end_time: Option<chrono::DateTime<chrono::Utc>>,
max_end_time: Option<chrono::DateTime<chrono::Utc>>,
likely_time: Option<chrono::DateTime<chrono::Utc>>,
}
@ -443,6 +450,9 @@ impl SignalGroup {
pub fn likely_time(&self) -> Option<chrono::prelude::DateTime<chrono::prelude::Utc>> {
self.likely_time
}
pub fn max_end_time(&self) -> Option<chrono::prelude::DateTime<chrono::prelude::Utc>> {
self.max_end_time
}
pub fn phase_to_str(&self) -> Option<String> {
self.phase.map(|v| {

View file

@ -207,7 +207,33 @@ async fn main(spawner: Spawner) -> ! {
staight_allowed: false,
right_allowed: false
},
end_sec: Some(23)
timing: Some(applogic::TimingData {
min_end_sec: 23,
likely_end_sec: None,
max_end_sec: None
})
}],
},
))
.inspect_err(log_screen_error);
embassy_time::Timer::after(embassy_time::Duration::from_secs(2)).await;
let _ = screen
.update(screen::ScreenState::GlosaLocked(
applogic::GlosaSignalInfo {
intersection_id: 1234,
signal_groups: alloc::vec![applogic::SignalGroupData {
phase: applogic::SignalPhase::Red,
maneuver: applogic::v2x::map::Maneuvers {
left_allowed: true,
staight_allowed: false,
right_allowed: false
},
timing: Some(applogic::TimingData {
min_end_sec: 23,
likely_end_sec: Some(24),
max_end_sec: Some(42)
})
}],
},
))
@ -508,8 +534,9 @@ async fn main(spawner: Spawner) -> ! {
if let applogic::GlosaOutput::Locked(data) = &glosa_data {
for sig in &data.signal_groups {
let duration_str = sig
.end_sec
.map(|v| alloc::format!("for {v} s"))
.timing
.as_ref()
.map(|v| alloc::format!("for {} s", v.min_end_sec))
.unwrap_or_default();
println!("GLOSA: {} {} {duration_str}", sig.maneuver, sig.phase);
}

View file

@ -86,6 +86,8 @@ where
const DEFAULT_TEXT_STYLE: mono_font::MonoTextStyle<'static, pixelcolor::Rgb565> =
mono_font::MonoTextStyle::new(&profont::PROFONT_24_POINT, Self::COLOR_FG);
const MID_TEXT_STYLE: mono_font::MonoTextStyle<'static, pixelcolor::Rgb565> =
mono_font::MonoTextStyle::new(&profont::PROFONT_18_POINT, Self::COLOR_FG);
const SMALL_TEXT_STYLE: mono_font::MonoTextStyle<'static, pixelcolor::Rgb565> =
mono_font::MonoTextStyle::new(&profont::PROFONT_14_POINT, Self::COLOR_FG);
@ -169,7 +171,7 @@ where
self.gnss_hb_state
);
// TODO: print on screen!
// TODO: print on screen?
self.gnss_hb_state = !self.gnss_hb_state;
@ -324,18 +326,39 @@ where
)
.draw(&mut self.target)?;
// draw timing indicator
if let Some(end_sec) = sig.end_sec {
text::Text::with_alignment(
&alloc::format!("{end_sec}s"),
geometry::Point::new(centerline, 160 + self.size.offset_top),
Self::DEFAULT_TEXT_STYLE,
text::Alignment::Center,
)
.draw(&mut self.target)?;
// draw timing indicator(s)
if let Some(timing) = &sig.timing {
if let (Some(likely), Some(max)) = (timing.likely_end_sec, timing.max_end_sec) {
text::Text::with_alignment(
&alloc::format!("{likely}s"),
geometry::Point::new(centerline, 160 + self.size.offset_top),
Self::DEFAULT_TEXT_STYLE,
text::Alignment::Center,
)
.draw(&mut self.target)?;
// TODO: only on big screen!?
text::Text::with_alignment(
&alloc::format!("{}-{max}s", timing.min_end_sec),
geometry::Point::new(centerline, 185 + self.size.offset_top),
Self::MID_TEXT_STYLE,
text::Alignment::Center,
)
.draw(&mut self.target)?;
} else {
text::Text::with_alignment(
&alloc::format!("{}s", timing.min_end_sec),
geometry::Point::new(centerline, 160 + self.size.offset_top),
Self::DEFAULT_TEXT_STYLE,
text::Alignment::Center,
)
.draw(&mut self.target)?;
}
}
}
// TODO: Add current speed and ETA
Ok(())
}