#[repr(transparent)]pub struct UnixSeconds(pub i64);Available on crate feature
wifi and target_os=none only.Expand description
Units-safe wrapper for Unix timestamps (seconds since 1970-01-01 00:00:00 UTC).
Tuple Fields§
§0: i64Implementations§
Source§impl UnixSeconds
impl UnixSeconds
Sourcepub const fn as_i64(self) -> i64
pub const fn as_i64(self) -> i64
Get the underlying i64 value.
Examples found in repository?
examples/wifi_auto.rs (line 151)
35async fn inner_main(spawner: Spawner) -> Result<Infallible> {
36 info!("Starting wifi_auto example");
37 let p = embassy_rp::init(Default::default());
38
39 // Initialize LED4 display
40 let cells = OutputArray::new([
41 gpio::Output::new(p.PIN_1, Level::High),
42 gpio::Output::new(p.PIN_2, Level::High),
43 gpio::Output::new(p.PIN_3, Level::High),
44 gpio::Output::new(p.PIN_4, Level::High),
45 ]);
46
47 let segments = OutputArray::new([
48 gpio::Output::new(p.PIN_5, Level::Low),
49 gpio::Output::new(p.PIN_6, Level::Low),
50 gpio::Output::new(p.PIN_7, Level::Low),
51 gpio::Output::new(p.PIN_8, Level::Low),
52 gpio::Output::new(p.PIN_9, Level::Low),
53 gpio::Output::new(p.PIN_10, Level::Low),
54 gpio::Output::new(p.PIN_11, Level::Low),
55 gpio::Output::new(p.PIN_12, Level::Low),
56 ]);
57
58 static LED4_STATIC: Led4Static = Led4::new_static();
59 let led4 = Led4::new(&LED4_STATIC, cells, segments, spawner)?;
60
61 let [
62 wifi_credentials_flash_block,
63 timezone_flash_block,
64 device_name_flash_block,
65 location_flash_block,
66 ] = FlashArray::<4>::new(p.FLASH)?;
67
68 static TIMEZONE_FIELD_STATIC: TimezoneFieldStatic = TimezoneField::new_static();
69 let timezone_field = TimezoneField::new(&TIMEZONE_FIELD_STATIC, timezone_flash_block);
70
71 static DEVICE_NAME_FIELD_STATIC: TextFieldStatic<32> = TextField::new_static();
72 let device_name_field = TextField::new(
73 &DEVICE_NAME_FIELD_STATIC,
74 device_name_flash_block,
75 "device_name",
76 "Device Name",
77 "www.picoclock.net",
78 );
79
80 static LOCATION_FIELD_STATIC: TextFieldStatic<64> = TextField::new_static();
81 let location_field = TextField::new(
82 &LOCATION_FIELD_STATIC,
83 location_flash_block,
84 "location",
85 "Location",
86 "Living Room",
87 );
88
89 let wifi_auto = WifiAuto::new(
90 p.PIN_23, // CYW43 power
91 p.PIN_24, // CYW43 clock
92 p.PIN_25, // CYW43 chip select
93 p.PIN_29, // CYW43 data pin
94 p.PIO0, // CYW43 PIO interface
95 p.DMA_CH0, // CYW43 DMA channel
96 wifi_credentials_flash_block, // Flash block storing Wi-Fi creds
97 p.PIN_13, // Reset button pin
98 PressedTo::Ground, // Button wiring
99 "Pico", // Captive portal SSID to display
100 [timezone_field, device_name_field, location_field],
101 spawner,
102 )?;
103
104 let led4_ref = &led4;
105 let (stack, mut button) = wifi_auto
106 .connect(|event| async move {
107 match event {
108 WifiAutoEvent::CaptivePortalReady => {
109 led4_ref.write_text(['C', 'O', 'N', 'N'], BlinkState::BlinkingAndOn);
110 }
111
112 WifiAutoEvent::Connecting { try_index, .. } => {
113 led4_ref.animate_text(circular_outline_animation((try_index & 1) == 0));
114 }
115
116 WifiAutoEvent::ConnectionFailed => {
117 led4_ref.write_text(['F', 'A', 'I', 'L'], BlinkState::BlinkingButOff);
118 }
119 }
120 Ok(())
121 })
122 .await?;
123
124 led4.write_text(['D', 'O', 'N', 'E'], BlinkState::Solid);
125
126 let timezone_offset_minutes = timezone_field
127 .offset_minutes()?
128 .ok_or(Error::MissingCustomWifiAutoField)?;
129 let device_name = device_name_field.text()?.unwrap_or_else(|| {
130 let mut name = String::new();
131 name.push_str("").expect("default name exceeds capacity");
132 name
133 });
134 let location = location_field.text()?.unwrap_or_else(|| {
135 let mut name = String::new();
136 name.push_str("Living Room")
137 .expect("default location exceeds capacity");
138 name
139 });
140 info!(
141 "Device '{}' in '{}' configured with timezone offset {} minutes",
142 device_name, location, timezone_offset_minutes
143 );
144
145 // At this point, `stack` can be used for internet access (HTTP, MQTT, etc.)
146 // and `button` can be used for user interactions (e.g., triggering actions).
147 info!("WiFi setup complete - press button to fetch NTP time");
148 loop {
149 button.wait_for_press().await;
150 match fetch_ntp_time(stack).await {
151 Ok(unix_seconds) => info!("Current time: {}", unix_seconds.as_i64()),
152 Err(err) => warn!("Failed to fetch time: {}", err),
153 }
154 }
155}Sourcepub const fn from_ntp_seconds(ntp: u32) -> Option<Self>
pub const fn from_ntp_seconds(ntp: u32) -> Option<Self>
Convert NTP seconds (since 1900-01-01) to Unix seconds (since 1970-01-01).
Examples found in repository?
examples/wifi_auto.rs (line 220)
157async fn fetch_ntp_time(stack: &'static Stack<'static>) -> Result<UnixSeconds, &'static str> {
158 use udp::UdpSocket;
159
160 const NTP_SERVER: &str = "pool.ntp.org";
161 const NTP_PORT: u16 = 123;
162
163 info!("Resolving {}...", NTP_SERVER);
164 let dns_result = stack
165 .dns_query(NTP_SERVER, DnsQueryType::A)
166 .await
167 .map_err(|e| {
168 warn!("DNS lookup failed: {:?}", e);
169 "DNS lookup failed"
170 })?;
171 let server_addr = dns_result.first().ok_or("No DNS results")?;
172
173 let mut rx_meta = [udp::PacketMetadata::EMPTY; 1];
174 let mut rx_buffer = [0; 128];
175 let mut tx_meta = [udp::PacketMetadata::EMPTY; 1];
176 let mut tx_buffer = [0; 128];
177 let mut socket = UdpSocket::new(
178 *stack,
179 &mut rx_meta,
180 &mut rx_buffer,
181 &mut tx_meta,
182 &mut tx_buffer,
183 );
184
185 socket.bind(0).map_err(|e| {
186 warn!("Socket bind failed: {:?}", e);
187 "Socket bind failed"
188 })?;
189
190 let mut ntp_request = [0u8; 48];
191 ntp_request[0] = 0x1B;
192 info!("Sending NTP request...");
193 socket
194 .send_to(&ntp_request, (*server_addr, NTP_PORT))
195 .await
196 .map_err(|e| {
197 warn!("NTP send failed: {:?}", e);
198 "NTP send failed"
199 })?;
200
201 let mut response = [0u8; 48];
202 let (n, _) =
203 embassy_time::with_timeout(Duration::from_secs(5), socket.recv_from(&mut response))
204 .await
205 .map_err(|_| {
206 warn!("NTP receive timeout");
207 "NTP receive timeout"
208 })?
209 .map_err(|e| {
210 warn!("NTP receive failed: {:?}", e);
211 "NTP receive failed"
212 })?;
213
214 if n < 48 {
215 warn!("NTP response too short: {} bytes", n);
216 return Err("NTP response too short");
217 }
218
219 let ntp_seconds = u32::from_be_bytes([response[40], response[41], response[42], response[43]]);
220 UnixSeconds::from_ntp_seconds(ntp_seconds).ok_or("Invalid NTP timestamp")
221}Sourcepub fn to_offset_datetime(self, offset: UtcOffset) -> Option<OffsetDateTime>
pub fn to_offset_datetime(self, offset: UtcOffset) -> Option<OffsetDateTime>
Convert to OffsetDateTime with the given timezone offset.
Trait Implementations§
Source§impl Clone for UnixSeconds
impl Clone for UnixSeconds
Source§fn clone(&self) -> UnixSeconds
fn clone(&self) -> UnixSeconds
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for UnixSeconds
impl Debug for UnixSeconds
Source§impl Format for UnixSeconds
impl Format for UnixSeconds
Source§impl Ord for UnixSeconds
impl Ord for UnixSeconds
Source§fn cmp(&self, other: &UnixSeconds) -> Ordering
fn cmp(&self, other: &UnixSeconds) -> Ordering
1.21.0 · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
Compares and returns the maximum of two values. Read more
Source§impl PartialEq for UnixSeconds
impl PartialEq for UnixSeconds
Source§impl PartialOrd for UnixSeconds
impl PartialOrd for UnixSeconds
impl Copy for UnixSeconds
impl Eq for UnixSeconds
impl StructuralPartialEq for UnixSeconds
Auto Trait Implementations§
impl Freeze for UnixSeconds
impl RefUnwindSafe for UnixSeconds
impl Send for UnixSeconds
impl Sync for UnixSeconds
impl Unpin for UnixSeconds
impl UnwindSafe for UnixSeconds
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CheckedAs for T
impl<T> CheckedAs for T
Source§fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
Casts the value.
Source§impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
Source§fn checked_cast_from(src: Src) -> Option<Dst>
fn checked_cast_from(src: Src) -> Option<Dst>
Casts the value.
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<Src, Dst> LosslessTryInto<Dst> for Srcwhere
Dst: LosslessTryFrom<Src>,
impl<Src, Dst> LosslessTryInto<Dst> for Srcwhere
Dst: LosslessTryFrom<Src>,
Source§fn lossless_try_into(self) -> Option<Dst>
fn lossless_try_into(self) -> Option<Dst>
Performs the conversion.
Source§impl<Src, Dst> LossyInto<Dst> for Srcwhere
Dst: LossyFrom<Src>,
impl<Src, Dst> LossyInto<Dst> for Srcwhere
Dst: LossyFrom<Src>,
Source§fn lossy_into(self) -> Dst
fn lossy_into(self) -> Dst
Performs the conversion.
Source§impl<T> OverflowingAs for T
impl<T> OverflowingAs for T
Source§fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
Casts the value.
Source§impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
Source§fn overflowing_cast_from(src: Src) -> (Dst, bool)
fn overflowing_cast_from(src: Src) -> (Dst, bool)
Casts the value.
Source§impl<T> SaturatingAs for T
impl<T> SaturatingAs for T
Source§fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
Casts the value.
Source§impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
Source§fn saturating_cast_from(src: Src) -> Dst
fn saturating_cast_from(src: Src) -> Dst
Casts the value.
Source§impl<T> StrictAs for T
impl<T> StrictAs for T
Source§fn strict_as<Dst>(self) -> Dstwhere
T: StrictCast<Dst>,
fn strict_as<Dst>(self) -> Dstwhere
T: StrictCast<Dst>,
Casts the value.
Source§impl<Src, Dst> StrictCastFrom<Src> for Dstwhere
Src: StrictCast<Dst>,
impl<Src, Dst> StrictCastFrom<Src> for Dstwhere
Src: StrictCast<Dst>,
Source§fn strict_cast_from(src: Src) -> Dst
fn strict_cast_from(src: Src) -> Dst
Casts the value.
Source§impl<T> UnwrappedAs for T
impl<T> UnwrappedAs for T
Source§fn unwrapped_as<Dst>(self) -> Dstwhere
T: UnwrappedCast<Dst>,
fn unwrapped_as<Dst>(self) -> Dstwhere
T: UnwrappedCast<Dst>,
Casts the value.
Source§impl<Src, Dst> UnwrappedCastFrom<Src> for Dstwhere
Src: UnwrappedCast<Dst>,
impl<Src, Dst> UnwrappedCastFrom<Src> for Dstwhere
Src: UnwrappedCast<Dst>,
Source§fn unwrapped_cast_from(src: Src) -> Dst
fn unwrapped_cast_from(src: Src) -> Dst
Casts the value.
Source§impl<T> WrappingAs for T
impl<T> WrappingAs for T
Source§fn wrapping_as<Dst>(self) -> Dstwhere
T: WrappingCast<Dst>,
fn wrapping_as<Dst>(self) -> Dstwhere
T: WrappingCast<Dst>,
Casts the value.
Source§impl<Src, Dst> WrappingCastFrom<Src> for Dstwhere
Src: WrappingCast<Dst>,
impl<Src, Dst> WrappingCastFrom<Src> for Dstwhere
Src: WrappingCast<Dst>,
Source§fn wrapping_cast_from(src: Src) -> Dst
fn wrapping_cast_from(src: Src) -> Dst
Casts the value.