Compare commits
4 Commits
b61fd153ca
...
presentati
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ee079736f | ||
|
|
b11b91c77d | ||
|
|
9cec79191c | ||
|
|
57d54182c3 |
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "untis-rs"]
|
||||||
|
path = untis-rs
|
||||||
|
url = https://github.com/zenonet/untis-rs.git
|
||||||
@@ -35,7 +35,7 @@ heapless = "0.8"
|
|||||||
esp-idf-sys = "0.36.1"
|
esp-idf-sys = "0.36.1"
|
||||||
anyhow = "1.0.99"
|
anyhow = "1.0.99"
|
||||||
embedded-svc = "0.28.1"
|
embedded-svc = "0.28.1"
|
||||||
untis = {path = "../untis-test/untis-rs"}
|
untis = { path = "untis-rs" }
|
||||||
chrono = "0.4.41"
|
chrono = "0.4.41"
|
||||||
embedded-layout = "0.4.2"
|
embedded-layout = "0.4.2"
|
||||||
u8g2-fonts = { version = "0.5.2", features = ["embedded_graphics_textstyle"] }
|
u8g2-fonts = { version = "0.5.2", features = ["embedded_graphics_textstyle"] }
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=14000
|
|||||||
# Workaround for https://github.com/espressif/esp-idf/issues/7631
|
# Workaround for https://github.com/espressif/esp-idf/issues/7631
|
||||||
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
|
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
|
||||||
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
|
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
|
||||||
|
CONFIG_ESP_TASK_WDT_EN=n
|
||||||
266
src/main.rs
266
src/main.rs
@@ -1,22 +1,28 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
use std::num::NonZeroU16;
|
use std::num::NonZeroU16;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
use std::{borrow::Cow};
|
use std::{borrow::Cow};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use chrono::{DateTime, Datelike, Days, FixedOffset, NaiveTime, TimeDelta, Weekday};
|
use chrono::{DateTime, Datelike, Days, FixedOffset, NaiveTime, TimeDelta, Weekday};
|
||||||
|
use embedded_graphics::prelude::DrawTarget;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
prelude::{Dimensions, Point},
|
prelude::{Dimensions, Point},
|
||||||
text::{Text},
|
text::{Text},
|
||||||
Drawable,
|
Drawable,
|
||||||
};
|
};
|
||||||
|
use embedded_hal::delay::DelayNs;
|
||||||
use epd_waveshare::{color::Color, epd7in5_v2::Epd7in5, prelude::WaveshareDisplay};
|
use epd_waveshare::{color::Color, epd7in5_v2::Epd7in5, prelude::WaveshareDisplay};
|
||||||
use esp_idf_hal::modem::Modem;
|
|
||||||
use esp_idf_hal::{
|
use esp_idf_hal::{
|
||||||
delay::{Ets},
|
delay::{Ets},
|
||||||
gpio::{Gpio19, PinDriver},
|
gpio::{Gpio19, PinDriver},
|
||||||
spi::{config, SpiDriverConfig},
|
spi::{config, SpiDriverConfig},
|
||||||
};
|
};
|
||||||
|
use esp_idf_svc::http::Method;
|
||||||
use esp_idf_svc::http::client::{Configuration as HttpConfig, EspHttpConnection};
|
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::wifi::{BlockingWifi, EspWifi};
|
||||||
use esp_idf_svc::{
|
use esp_idf_svc::{
|
||||||
eventloop::EspSystemEventLoop,
|
eventloop::EspSystemEventLoop,
|
||||||
@@ -24,7 +30,7 @@ use esp_idf_svc::{
|
|||||||
nvs::EspDefaultNvsPartition,
|
nvs::EspDefaultNvsPartition,
|
||||||
wifi::Configuration,
|
wifi::Configuration,
|
||||||
};
|
};
|
||||||
use esp_idf_sys::esp_deep_sleep;
|
use esp_idf_sys::{esp_deep_sleep, esp_deep_sleep_wake_stub_fn_t};
|
||||||
use u8g2_fonts::U8g2TextStyle;
|
use u8g2_fonts::U8g2TextStyle;
|
||||||
use untis::{Date, Lesson, LessonCode};
|
use untis::{Date, Lesson, LessonCode};
|
||||||
use embedded_layout::{layout::linear::{spacing::DistributeFill, FixedMargin, LinearLayout}, prelude::*};
|
use embedded_layout::{layout::linear::{spacing::DistributeFill, FixedMargin, LinearLayout}, prelude::*};
|
||||||
@@ -40,6 +46,8 @@ static mut FETCHING_FAIL_COUNT: Option<NonZeroU16> = None;
|
|||||||
#[unsafe(link_section = ".rtc.data")]
|
#[unsafe(link_section = ".rtc.data")]
|
||||||
static mut ERROR_MSG: Option<[u8; 2048]> = None;
|
static mut ERROR_MSG: Option<[u8; 2048]> = None;
|
||||||
|
|
||||||
|
static mut WEEK_OFFSET: i32 = 0;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
// It is necessary to call this function once. Otherwise some patches to the runtime
|
// It is necessary to call this function once. Otherwise some patches to the runtime
|
||||||
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
||||||
@@ -51,15 +59,11 @@ fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
log::info!("Took peripherals");
|
log::info!("Took peripherals");
|
||||||
|
|
||||||
let busy = PinDriver::input(peripherals.pins.gpio17).unwrap();
|
let mut creds = include_str!("../wifi-creds.txt").split('\n');
|
||||||
let rst = PinDriver::output(peripherals.pins.gpio16).unwrap();
|
let ssid: heapless::String<32> =
|
||||||
let cs = peripherals.pins.gpio5;
|
heapless::String::<32>::from_str(creds.next().unwrap()).unwrap();
|
||||||
let clk = peripherals.pins.gpio18;
|
let password: heapless::String<64> =
|
||||||
let mosi = peripherals.pins.gpio23;
|
heapless::String::<64>::from_str(creds.next().unwrap()).unwrap();
|
||||||
let miso = peripherals.pins.gpio19; // aka. dc
|
|
||||||
|
|
||||||
let dc = PinDriver::output(miso).unwrap();
|
|
||||||
|
|
||||||
|
|
||||||
std::panic::set_hook(Box::new(|panic|{
|
std::panic::set_hook(Box::new(|panic|{
|
||||||
let msg: String = format!("{}", panic);/* if let Some(s) = panic.payload().downcast_ref::<&str>() {
|
let msg: String = format!("{}", panic);/* if let Some(s) = panic.payload().downcast_ref::<&str>() {
|
||||||
@@ -86,6 +90,15 @@ fn main() -> anyhow::Result<()> {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
let busy = PinDriver::input(peripherals.pins.gpio17).unwrap();
|
||||||
|
let rst = PinDriver::output(peripherals.pins.gpio16).unwrap();
|
||||||
|
let cs = peripherals.pins.gpio5;
|
||||||
|
let clk = peripherals.pins.gpio18;
|
||||||
|
let mosi = peripherals.pins.gpio23;
|
||||||
|
let miso = peripherals.pins.gpio19; // aka. dc
|
||||||
|
|
||||||
|
let dc = PinDriver::output(miso).unwrap();
|
||||||
|
|
||||||
log::info!("Initialized pins");
|
log::info!("Initialized pins");
|
||||||
|
|
||||||
let config = config::Config::new();
|
let config = config::Config::new();
|
||||||
@@ -103,17 +116,21 @@ fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
log::info!("Initialized spi interface");
|
log::info!("Initialized spi interface");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Initialize the draw buffer
|
// Initialize the draw buffer
|
||||||
// Allocating on the stack makes the chip crash. We gotta put it on the heap
|
// 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());
|
let mut display = Box::new(epd_waveshare::epd7in5_v2::Display7in5::default());
|
||||||
display.set_rotation(epd_waveshare::prelude::DisplayRotation::Rotate0);
|
display.set_rotation(epd_waveshare::prelude::DisplayRotation::Rotate0);
|
||||||
|
|
||||||
unsafe {
|
|
||||||
WAKEUP_COUNTER += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut delay = Ets;
|
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{
|
unsafe{
|
||||||
if let Some(error) = ERROR_MSG{
|
if let Some(error) = ERROR_MSG{
|
||||||
|
|
||||||
@@ -135,7 +152,6 @@ fn main() -> anyhow::Result<()> {
|
|||||||
.arrange()
|
.arrange()
|
||||||
.draw(&mut *display).unwrap();
|
.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.update_and_display_frame(&mut spi, &*display.buffer(), &mut delay)?;
|
||||||
epd7in5.sleep(&mut spi, &mut delay)?;
|
epd7in5.sleep(&mut spi, &mut delay)?;
|
||||||
|
|
||||||
@@ -144,8 +160,142 @@ 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){
|
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
},
|
||||||
|
))?;
|
||||||
|
|
||||||
|
fn err() -> !{
|
||||||
|
println!("No wifi available. Sleeping for 5 minutes");
|
||||||
|
unsafe{
|
||||||
|
// retry in 5 minutes
|
||||||
|
esp_deep_sleep(5*60*1000_000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wifi.start().unwrap_or_else(|_| err());
|
||||||
|
wifi.connect().unwrap_or_else(|_| err());
|
||||||
|
wifi.wait_netif_up().unwrap_or_else(|_| err());
|
||||||
|
loop {if wifi.is_connected().unwrap_or_else(|_| err()) {break;}};
|
||||||
|
|
||||||
|
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(Option::<Command>::None));
|
||||||
|
let writer = do_update.clone();
|
||||||
|
httpserver.fn_handler("/", Method::Get, move |request| -> anyhow::Result<()> {
|
||||||
|
|
||||||
|
*writer.write().unwrap() = Some(Command::Timetable);
|
||||||
|
|
||||||
|
unsafe{
|
||||||
|
WEEK_OFFSET = request.header("week").and_then(|w| w.parse::<i32>().ok()).unwrap_or_default();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let writer = do_update.clone();
|
||||||
|
httpserver.fn_handler("/msg", Method::Get, move |request| -> anyhow::Result<()> {
|
||||||
|
|
||||||
|
*writer.write().unwrap() = Some(Command::Message(request.header("msg").unwrap().to_string()));
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
match &*do_update.read().unwrap(){
|
||||||
|
Some(Command::Timetable) => {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(Command::Message(msg)) => {
|
||||||
|
display_custom_message(&mut display, &msg);
|
||||||
|
|
||||||
|
epd7in5.wake_up(&mut spi, &mut delay)?;
|
||||||
|
epd7in5.update_and_display_frame(&mut spi, &*display.buffer(), &mut delay)?;
|
||||||
|
epd7in5.sleep(&mut spi, &mut delay)?;
|
||||||
|
}
|
||||||
|
None => continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(mut writer) = do_update.try_write(){
|
||||||
|
*writer = Option::<Command>::None;
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
enum Command{
|
||||||
|
Timetable,
|
||||||
|
Message(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_display_buffer(display: &mut epd_waveshare::epd7in5_v2::Display7in5){
|
||||||
|
let (tt, now) = match fetch_data(){
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let fail_count: u16 = unsafe {
|
let fail_count: u16 = unsafe {
|
||||||
@@ -175,34 +325,30 @@ 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
|
// 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();
|
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
|
// Render the layout
|
||||||
draw_layout(&mut display, &tt, now, next_wakeup_time, include_str!("../wifi-creds.txt").split('\n').next().unwrap());
|
draw_layout(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn display_custom_message(display: &mut epd_waveshare::epd7in5_v2::Display7in5, msg: &str){
|
||||||
|
display.clear(Color::Black).unwrap();
|
||||||
|
let text_style = U8g2TextStyle::new(u8g2_fonts::fonts::u8g2_font_profont22_mr, Color::White);
|
||||||
|
|
||||||
|
let display_area = display.bounding_box();
|
||||||
|
let text = Text::new(msg, Point::zero(), &text_style);
|
||||||
|
|
||||||
|
LinearLayout::vertical(Chain::new(text))
|
||||||
|
.with_alignment(horizontal::Center)
|
||||||
|
.arrange()
|
||||||
|
.align_to(&display_area, horizontal::Center, vertical::Center)
|
||||||
|
.draw(display)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
fn get_full_subject_name(shortname: &str) -> Option<&'static str>{
|
fn get_full_subject_name(shortname: &str) -> Option<&'static str>{
|
||||||
if shortname.len() < 2{
|
if shortname.len() < 2{
|
||||||
return None;
|
return None;
|
||||||
@@ -247,38 +393,7 @@ fn calculate_next_wakeuptime(now: DateTime<FixedOffset>) -> Option<DateTime<Fixe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_data(modem: Modem) -> anyhow::Result<(Box<Timetable>, DateTime<FixedOffset>)>{
|
fn fetch_data() -> anyhow::Result<(Box<Timetable>, DateTime<FixedOffset>)>{
|
||||||
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");
|
|
||||||
|
|
||||||
let httpconnection = EspHttpConnection::new(&HttpConfig {
|
let httpconnection = EspHttpConnection::new(&HttpConfig {
|
||||||
use_global_ca_store: true,
|
use_global_ca_store: true,
|
||||||
crt_bundle_attach: Some(esp_idf_sys::esp_crt_bundle_attach),
|
crt_bundle_attach: Some(esp_idf_sys::esp_crt_bundle_attach),
|
||||||
@@ -287,9 +402,6 @@ fn fetch_data(modem: Modem) -> anyhow::Result<(Box<Timetable>, DateTime<FixedOff
|
|||||||
|
|
||||||
let res = fetch_timetable(httpconnection);
|
let res = fetch_timetable(httpconnection);
|
||||||
|
|
||||||
wifi.disconnect().unwrap();
|
|
||||||
wifi.stop().unwrap();
|
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,10 +566,10 @@ fn fetch_timetable(client: EspHttpConnection) -> anyhow::Result<(Box<Timetable>,
|
|||||||
password,
|
password,
|
||||||
client
|
client
|
||||||
).or_else(|e| None.context(format!("{:?}", e)))?;
|
).or_else(|e| None.context(format!("{:?}", e)))?;
|
||||||
let cest = chrono::FixedOffset::east_opt(2 * 3600).unwrap();
|
let cet = chrono::FixedOffset::east_opt(1 * 3600).unwrap();
|
||||||
let now = s.date().context("Untis client provided no time but time is necessary for the requesting the timetable")?.with_timezone(&cest);
|
let now = s.date().context("Untis client provided no time but time is necessary for the requesting the timetable")?.with_timezone(&cet);
|
||||||
println!("Current time: {}", now);
|
println!("Current time: {}", now);
|
||||||
let date = now.date_naive().checked_add_days(Days::new(2)).unwrap();
|
let date = now.date_naive().checked_add_days(Days::new(2)).unwrap().checked_add_signed(TimeDelta::weeks(unsafe { WEEK_OFFSET } as i64 )).unwrap();
|
||||||
let lessons = s.own_timetable_for_week(&Date(date)).or_else(|e| None.context(format!("{:?}", e)))?;
|
let lessons = s.own_timetable_for_week(&Date(date)).or_else(|e| None.context(format!("{:?}", e)))?;
|
||||||
|
|
||||||
Ok((transform_lessons(lessons), now))
|
Ok((transform_lessons(lessons), now))
|
||||||
|
|||||||
1
untis-rs
Submodule
1
untis-rs
Submodule
Submodule untis-rs added at 2245aff545
Reference in New Issue
Block a user