Sort of working version

No integration with Wallas Heater itself, but boots
and connects to preconfigured Wifi - fetches time and
can display HTML pages.
This commit is contained in:
2025-01-16 10:23:54 +01:00
parent 60b394f24d
commit 86ccf24333
8 changed files with 121 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
resources/risc-v-core.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

99
src/sntp_client.rs Normal file
View File

@@ -0,0 +1,99 @@
use core::net::{IpAddr, SocketAddr};
use embassy_net::Stack;
use embassy_net::dns::DnsQueryType;
use embassy_time::{Duration, Instant, Timer};
use embassy_net::udp::{PacketMetadata, UdpSocket};
use embassy_sync::watch::Watch;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use alloc::string::String;
use log::error;
use sntpc::{get_time, NtpContext, NtpTimestampGenerator};
use chrono::{DateTime, Utc};
#[derive(Copy, Clone)]
struct Timestamp {
tstamp: Instant,
}
static UTC_DATETIME: Watch<CriticalSectionRawMutex, Duration, 2> = Watch::new();
pub fn get_now() -> String {
let offset = UTC_DATETIME.try_get();
match offset {
None => {
alloc::format!("LAUNCH+{}s", Instant::now().as_secs())
},
Some(duration) => {
let now = Instant::now() + duration;
let micros: i64 = now.as_micros() as i64;
let dt = DateTime::<Utc>::from_timestamp_micros(micros);
match dt {
Some(val) => alloc::format!("{}", val.format("%Y-%m-%d %H:%M:%S")),
None => alloc::format!("LAUNCH+{}s", Instant::now().as_secs())
}
}
}
}
impl NtpTimestampGenerator for Timestamp {
fn init(&mut self) {
self.tstamp = Instant::now();
}
fn timestamp_sec(&self) -> u64 {
self.tstamp.as_secs()
}
fn timestamp_subsec_micros(&self) -> u32 {
(self.tstamp.as_micros() % 1_000_000) as u32
}
}
pub fn sntp_client_spawn(spawner: embassy_executor::Spawner, stack: Stack<'static>) {
spawner.must_spawn(sntp_client(stack));
}
#[embassy_executor::task]
async fn sntp_client(stack: Stack<'static>) {
// Create UDP socket
let mut rx_meta = [PacketMetadata::EMPTY; 16];
let mut rx_buffer = [0; 4096];
let mut tx_meta = [PacketMetadata::EMPTY; 16];
let mut tx_buffer = [0; 4096];
let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
socket.bind(123).unwrap();
let context = NtpContext::new(Timestamp{tstamp: Instant::now()});
let server_list : alloc::vec::Vec<&str> = alloc::vec!["0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org", "3.pool.ntp.org"];
let mut current_server = 2;
let sender = UTC_DATETIME.sender();
loop {
let dns_res = stack.dns_query (server_list[current_server], DnsQueryType::A).await.expect("Failed to resolve NTP server");
let addr: IpAddr = dns_res[0].into();
let result =
get_time(SocketAddr::from((addr, 123)), &socket, context).await;
match result {
Ok(time) => {
let offset = Duration::from_micros(time.offset as u64);
sender.send(offset);
Timer::after(Duration::from_secs(7*24*3600)).await; // redo SNTP check in a week
}
Err(e) => {
error!("Error getting time: {:?}", e);
current_server = (current_server + 1) % 4;
Timer::after(Duration::from_secs(30)).await;
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
src/static/risc-v-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

22
src/static/styles.css Normal file
View File

@@ -0,0 +1,22 @@
body {
font-family: serif;
text-align: center;
color: #321C0B;
background-color: #D5E4F6;
height: 100%;
}
h1 {
color: #B15C1B;
}
h4 {
color: #2969B2;
}
p.intro {
border: 1px solid #B15C1B;
padding: 0.2em;
margin: 0.3em 10vw 0.3em 10vw;
}
div#footer {
position: absolute;
bottom: 0px;
}

BIN
src/static/wallas-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB