diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3a4ddfc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "untis-rs"] + path = untis-rs + url = https://github.com/zenonet/untis-rs.git diff --git a/Cargo.toml b/Cargo.toml index 3f3173b..dbcf41d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ heapless = "0.8" esp-idf-sys = "0.36.1" anyhow = "1.0.99" embedded-svc = "0.28.1" -untis = {path = "../untis-test/untis-rs"} +untis = { path = "untis-rs" } chrono = "0.4.41" embedded-layout = "0.4.2" u8g2-fonts = { version = "0.5.2", features = ["embedded_graphics_textstyle"] } diff --git a/sdkconfig.defaults b/sdkconfig.defaults index fb4b8df..beb7525 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -8,3 +8,4 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=14000 # Workaround for https://github.com/espressif/esp-idf/issues/7631 #CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n #CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n +CONFIG_ESP_TASK_WDT_EN=n \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 136b6ae..db5bbfe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,30 @@ +use std::cell::RefCell; use std::num::NonZeroU16; +use std::ops::Deref; +use std::sync::{Arc, RwLock}; use std::{borrow::Cow}; use std::str::FromStr; use anyhow::Context; use chrono::{DateTime, Datelike, Days, FixedOffset, NaiveTime, TimeDelta, Weekday}; +use embedded_graphics::prelude::DrawTarget; use embedded_graphics::{ prelude::{Dimensions, Point}, text::{Text}, Drawable, }; +use embedded_hal::delay::DelayNs; use epd_waveshare::{color::Color, epd7in5_v2::Epd7in5, prelude::WaveshareDisplay}; +use esp_idf_hal::delay::Delay; use esp_idf_hal::modem::Modem; use esp_idf_hal::{ delay::{Ets}, gpio::{Gpio19, PinDriver}, spi::{config, SpiDriverConfig}, }; +use esp_idf_svc::http::Method; use esp_idf_svc::http::client::{Configuration as HttpConfig, EspHttpConnection}; +use esp_idf_svc::http::server::EspHttpServer; use esp_idf_svc::wifi::{BlockingWifi, EspWifi}; use esp_idf_svc::{ eventloop::EspSystemEventLoop, @@ -103,17 +111,21 @@ fn main() -> anyhow::Result<()> { log::info!("Initialized spi interface"); + + + + // Initialize the draw buffer // Allocating on the stack makes the chip crash. We gotta put it on the heap let mut display = Box::new(epd_waveshare::epd7in5_v2::Display7in5::default()); display.set_rotation(epd_waveshare::prelude::DisplayRotation::Rotate0); - unsafe { - WAKEUP_COUNTER += 1; - } - let mut delay = Ets; + let mut epd7in5 = Epd7in5::new(&mut spi, busy, dc, rst, &mut delay, None).unwrap(); + epd7in5.sleep(&mut spi, &mut delay)?; + log::info!("Completed"); + unsafe{ if let Some(error) = ERROR_MSG{ @@ -135,7 +147,6 @@ fn main() -> anyhow::Result<()> { .arrange() .draw(&mut *display).unwrap(); - let mut epd7in5 = Epd7in5::new(&mut spi, busy, dc, rst, &mut delay, None).unwrap(); epd7in5.update_and_display_frame(&mut spi, &*display.buffer(), &mut delay)?; epd7in5.sleep(&mut spi, &mut delay)?; @@ -144,8 +155,102 @@ fn main() -> anyhow::Result<()> { } } - // Create a file called wifi-creds.txt and write SSID and password into it separated by a line break - let (tt, now) = match fetch_data(peripherals.modem){ + let mut creds = include_str!("../wifi-creds.txt").split('\n'); + let ssid: heapless::String<32> = + heapless::String::<32>::from_str(creds.next().unwrap()).unwrap(); + let password: heapless::String<64> = + heapless::String::<64>::from_str(creds.next().unwrap()).unwrap(); + + // Connecting to wifi + let sysloop = EspSystemEventLoop::take()?; + let nvs = EspDefaultNvsPartition::take()?; + let mut wifi = BlockingWifi::wrap( + EspWifi::new(peripherals.modem, sysloop.clone(), Some(nvs))?, + sysloop.clone(), + )?; + + wifi.set_configuration(&Configuration::Client( + esp_idf_svc::wifi::ClientConfiguration { + ssid, + password, + auth_method: esp_idf_svc::wifi::AuthMethod::WPA2WPA3Personal, + ..Default::default() + }, + ))?; + + wifi.start() + .and_then(|_| wifi.connect()) + .and_then(|_| wifi.wait_netif_up()) + .and_then(|_| loop {if wifi.is_connected().unwrap() {break Ok(());}})?; + + unsafe { + FETCHING_FAIL_COUNT = None; + } + + + let mut httpserver = EspHttpServer::new(&esp_idf_svc::http::server::Configuration{ + http_port: 80, + ..Default::default() + })?; + + let do_update = Arc::new(RwLock::new(false)); + let writer = do_update.clone(); + httpserver.fn_handler("/", Method::Get, move |request| -> anyhow::Result<()> { + + *writer.write().unwrap() = true; + + + // Retrieve html String + let html = String::from("OK"); + // Respond with OK status + let mut response = request.into_ok_response()?; + // Return Requested Object (Index Page) + response.write(html.as_bytes())?; + Ok(()) + })?; + + loop { + delay.delay_ns(100); + + if *do_update.read().unwrap(){ + update_display_buffer(&mut display); + println!("Rendered to buffer"); + epd7in5.wake_up(&mut spi, &mut delay)?; + epd7in5.update_and_display_frame(&mut spi, &*display.buffer(), &mut delay)?; + println!("Updated frame"); + epd7in5.sleep(&mut spi, &mut delay)?; + println!("Sleep"); + unsafe { + WAKEUP_COUNTER += 1; + } + + if let Ok(mut writer) = do_update.try_write(){ + *writer = false; + println!("Successfully reset rw lock") + } + } + } + + + + drop(httpserver); + drop(epd7in5); + drop(spi); + + //let next_wakeup_time = calculate_next_wakeuptime(now).context(format!("Failed to calculate next wakeup time for time {now}")).unwrap(); + //let seconds_until_wakeup = next_wakeup_time.timestamp() - now.timestamp(); + + wifi.disconnect().unwrap(); + wifi.stop().unwrap(); + +/* unsafe{ + esp_deep_sleep(seconds_until_wakeup as u64 * 1000_000); + } */ + Ok(()) +} + +fn update_display_buffer(display: &mut epd_waveshare::epd7in5_v2::Display7in5){ + let (tt, now) = match fetch_data(){ Ok(d) => d, Err(e) => { let fail_count: u16 = unsafe { @@ -175,31 +280,12 @@ fn main() -> anyhow::Result<()> { } }; - unsafe { - FETCHING_FAIL_COUNT = None; - } - - // We wanna panic here if this fails because retrying this in a couple of seconds is stupid let next_wakeup_time = calculate_next_wakeuptime(now).context(format!("Failed to calculate next wakeup time for time {now}")).unwrap(); + display.clear(Color::Black).unwrap(); // Render the layout - draw_layout(&mut display, &tt, now, next_wakeup_time, include_str!("../wifi-creds.txt").split('\n').next().unwrap()); - - // Actually push changes to the display - let mut epd7in5 = Epd7in5::new(&mut spi, busy, dc, rst, &mut delay, None).unwrap(); - epd7in5.update_and_display_frame(&mut spi, &*display.buffer(), &mut delay)?; - epd7in5.sleep(&mut spi, &mut delay)?; - log::info!("Completed"); - - drop(epd7in5); - drop(spi); - - let seconds_until_wakeup = next_wakeup_time.timestamp() - now.timestamp(); - - unsafe{ - esp_deep_sleep(seconds_until_wakeup as u64 * 1000_000); - } + draw_layout(display, &tt, now, next_wakeup_time, include_str!("../wifi-creds.txt").split('\n').next().unwrap()); } @@ -247,38 +333,7 @@ fn calculate_next_wakeuptime(now: DateTime) -> Option anyhow::Result<(Box, DateTime)>{ - let mut creds = include_str!("../wifi-creds.txt").split('\n'); - let ssid: heapless::String<32> = - heapless::String::<32>::from_str(creds.next().unwrap()).unwrap(); - let password: heapless::String<64> = - heapless::String::<64>::from_str(creds.next().unwrap()).unwrap(); - - // Connecting to wifi - let sysloop = EspSystemEventLoop::take()?; - let nvs = EspDefaultNvsPartition::take()?; - let mut wifi = BlockingWifi::wrap( - EspWifi::new(modem, sysloop.clone(), Some(nvs))?, - sysloop.clone(), - )?; - - wifi.set_configuration(&Configuration::Client( - esp_idf_svc::wifi::ClientConfiguration { - ssid, - password, - auth_method: esp_idf_svc::wifi::AuthMethod::WPA2WPA3Personal, - ..Default::default() - }, - ))?; - - wifi.start() - .and_then(|_| wifi.connect()) - .and_then(|_| wifi.wait_netif_up()) - .and_then(|_| loop {if wifi.is_connected().unwrap() {break Ok(());}})?; - - - println!("Connected to wifi"); - +fn fetch_data() -> anyhow::Result<(Box, DateTime)>{ let httpconnection = EspHttpConnection::new(&HttpConfig { use_global_ca_store: true, crt_bundle_attach: Some(esp_idf_sys::esp_crt_bundle_attach), @@ -287,9 +342,6 @@ fn fetch_data(modem: Modem) -> anyhow::Result<(Box, DateTime