ups-esp32c3-rust/src/time.rs

106 lines
3.1 KiB
Rust

use anyhow::bail;
use embedded_svc::sys_time::SystemTime;
use esp_idf_svc::sntp::{self, EspSntp};
use esp_idf_svc::systime::EspSystemTime;
use log::{warn, info};
use sntpc::{Error, NtpContext, NtpResult, NtpTimestampGenerator, NtpUdpSocket, Result};
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
use std::time::{Duration};
pub struct Time {
result: Option<NtpResult>,
sntp: Option<Box<EspSntp>>,
}
impl Time {
pub fn new () -> Time {
return Time {
result: None,
sntp: None
}
}
pub fn sync(&mut self) -> anyhow::Result<()> {
let sntp = sntp::EspSntp::new_default().map_err(|err| {
anyhow::anyhow!("ESP SNTP Failed: {:?}", err)
})?;
self.sntp = Some(Box::new(sntp));
return anyhow::Ok(())
}
pub fn get_time(&mut self) -> Duration {
if let Some(ref mut sntp) = self.sntp {
info!("ESP SNTP sync status {:?}", sntp.get_sync_status());
}
EspSystemTime {}.now()
}
// pub fn sync(&mut self) -> anyhow::Result<()> {
// let mut error = None;
// for _ in 0..10 {
// let socket = UdpSocket::bind("0.0.0.0:0").expect("Unable to crate UDP socket");
// socket
// .set_read_timeout(Some(Duration::from_secs(2)))
// .expect("Unable to set UDP socket read timeout");
// let sock_wrapper = UdpSocketWrapper(socket);
// let ntp_context = NtpContext::new(StdTimestampGen::default());
// let result = sntpc::get_time("pool.ntp.org:123", sock_wrapper, ntp_context);
// match result {
// Ok(res_time) => {
// println!("Got time: {}.{}", res_time.sec(), res_time.sec_fraction());
// self.result = Some(res_time);
// return anyhow::Ok(())
// }
// Err(err) => {
// error = Some(err);
// warn!("fetch dateTime from ntp failed: {:?}", err);
// },
// }
// }
// bail!("fetch dateTime from ntp failed: {:?}", error)
// }
}
#[derive(Copy, Clone, Default)]
struct StdTimestampGen {
duration: Duration,
}
impl NtpTimestampGenerator for StdTimestampGen {
fn init(&mut self) {
self.duration = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.unwrap();
}
fn timestamp_sec(&self) -> u64 {
self.duration.as_secs()
}
fn timestamp_subsec_micros(&self) -> u32 {
self.duration.subsec_micros()
}
}
#[derive(Debug)]
struct UdpSocketWrapper(UdpSocket);
impl NtpUdpSocket for UdpSocketWrapper {
fn send_to<T: ToSocketAddrs>(&self, buf: &[u8], addr: T) -> Result<usize> {
match self.0.send_to(buf, addr) {
Ok(usize) => Ok(usize),
Err(_) => Err(Error::Network),
}
}
fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
match self.0.recv_from(buf) {
Ok((size, addr)) => Ok((size, addr)),
Err(_) => Err(Error::Network),
}
}
}