get log to work, make time accessible
This commit is contained in:
		@@ -1,9 +1,9 @@
 | 
			
		||||
use crate::config::{NetworkConfig, PlantControllerConfig};
 | 
			
		||||
use crate::hal::{GW_IP_ADDR_ENV, PLANT_COUNT};
 | 
			
		||||
use crate::log::{log, LogMessage};
 | 
			
		||||
use crate::hal::{GW_IP_ADDR_ENV, PLANT_COUNT, TIME_ACCESS};
 | 
			
		||||
use crate::log::{ LogArray, LogMessage, LOG_ACCESS};
 | 
			
		||||
use crate::STAY_ALIVE;
 | 
			
		||||
use anyhow::{anyhow, bail, Context};
 | 
			
		||||
use chrono::{DateTime, Utc};
 | 
			
		||||
use chrono::{DateTime, FixedOffset, Utc};
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
 | 
			
		||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
 | 
			
		||||
@@ -13,12 +13,10 @@ use alloc::{format, string::String, vec::Vec};
 | 
			
		||||
use core::marker::PhantomData;
 | 
			
		||||
use core::net::{IpAddr, Ipv4Addr};
 | 
			
		||||
use core::str::FromStr;
 | 
			
		||||
use embassy_executor::{SendSpawner, Spawner};
 | 
			
		||||
use embassy_net::tcp::TcpSocket;
 | 
			
		||||
use embassy_net::{IpListenEndpoint, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
 | 
			
		||||
use embassy_executor::{Spawner};
 | 
			
		||||
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
 | 
			
		||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 | 
			
		||||
use embassy_sync::mutex::Mutex;
 | 
			
		||||
use embassy_sync::rwlock::TryLockError;
 | 
			
		||||
use embassy_time::{Duration, Instant, Timer};
 | 
			
		||||
use embedded_storage::nor_flash::ReadNorFlash;
 | 
			
		||||
use embedded_storage::Storage;
 | 
			
		||||
@@ -26,25 +24,27 @@ use esp_bootloader_esp_idf::ota::{Ota, OtaImageState, Slot};
 | 
			
		||||
use esp_bootloader_esp_idf::partitions::{Error, FlashRegion, PartitionEntry, PartitionTable};
 | 
			
		||||
use esp_hal::gpio::Input;
 | 
			
		||||
use esp_hal::rng::Rng;
 | 
			
		||||
use esp_hal::rtc_cntl::Rtc;
 | 
			
		||||
use esp_hal::rtc_cntl::sleep::RtcSleepConfig;
 | 
			
		||||
use esp_println::{print, println};
 | 
			
		||||
use esp_hal::system::software_reset;
 | 
			
		||||
use esp_println::{println};
 | 
			
		||||
use esp_storage::FlashStorage;
 | 
			
		||||
use esp_wifi::wifi::{
 | 
			
		||||
    AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
 | 
			
		||||
    ScanTypeConfig, WifiController, WifiDevice, WifiEvent, WifiState,
 | 
			
		||||
    ScanTypeConfig, WifiController, WifiDevice,
 | 
			
		||||
};
 | 
			
		||||
use littlefs2::fs::Filesystem;
 | 
			
		||||
use littlefs2_core::{DynFile, FileType, OpenSeekFrom, Path, PathBuf, SeekFrom};
 | 
			
		||||
use log::{info, warn};
 | 
			
		||||
use littlefs2_core::{DynFile, FileType, PathBuf, SeekFrom};
 | 
			
		||||
use log::{info};
 | 
			
		||||
 | 
			
		||||
#[link_section = ".rtc.data"]
 | 
			
		||||
#[esp_hal::ram(rtc_fast, persistent)]
 | 
			
		||||
static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT];
 | 
			
		||||
#[link_section = ".rtc.data"]
 | 
			
		||||
#[esp_hal::ram(rtc_fast, persistent)]
 | 
			
		||||
static mut CONSECUTIVE_WATERING_PLANT: [u32; PLANT_COUNT] = [0; PLANT_COUNT];
 | 
			
		||||
#[link_section = ".rtc.data"]
 | 
			
		||||
static mut LOW_VOLTAGE_DETECTED: bool = false;
 | 
			
		||||
#[link_section = ".rtc.data"]
 | 
			
		||||
static mut RESTART_TO_CONF: bool = false;
 | 
			
		||||
#[esp_hal::ram(rtc_fast, persistent)]
 | 
			
		||||
static mut LOW_VOLTAGE_DETECTED: i8 = 0;
 | 
			
		||||
#[esp_hal::ram(rtc_fast, persistent)]
 | 
			
		||||
static mut RESTART_TO_CONF: i8 = 0;
 | 
			
		||||
 | 
			
		||||
static CONFIG_FILE: &str = "config.json";
 | 
			
		||||
 | 
			
		||||
@@ -239,10 +239,6 @@ impl Esp<'_> {
 | 
			
		||||
        bail!("not implemented")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn time(&mut self) -> DateTime<Utc> {
 | 
			
		||||
        let wall_clock = Instant::now().as_millis() + self.wall_clock_offset;
 | 
			
		||||
        DateTime::from_timestamp_millis(wall_clock as i64).unwrap()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) async fn wifi_scan(&mut self) -> anyhow::Result<Vec<AccessPointInfo>> {
 | 
			
		||||
        info!("start wifi scan");
 | 
			
		||||
@@ -277,17 +273,17 @@ impl Esp<'_> {
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_low_voltage_in_cycle(&mut self) {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            LOW_VOLTAGE_DETECTED = true;
 | 
			
		||||
            LOW_VOLTAGE_DETECTED = 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn clear_low_voltage_in_cycle(&mut self) {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            LOW_VOLTAGE_DETECTED = false;
 | 
			
		||||
            LOW_VOLTAGE_DETECTED = 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub(crate) fn low_voltage_in_cycle(&mut self) -> bool {
 | 
			
		||||
        unsafe { LOW_VOLTAGE_DETECTED }
 | 
			
		||||
        unsafe { LOW_VOLTAGE_DETECTED == 1 }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn store_consecutive_pump_count(&mut self, plant: usize, count: u32) {
 | 
			
		||||
        unsafe {
 | 
			
		||||
@@ -298,11 +294,15 @@ impl Esp<'_> {
 | 
			
		||||
        unsafe { CONSECUTIVE_WATERING_PLANT[plant] }
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn get_restart_to_conf(&mut self) -> bool {
 | 
			
		||||
        unsafe { RESTART_TO_CONF }
 | 
			
		||||
        unsafe { RESTART_TO_CONF  == 1}
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn set_restart_to_conf(&mut self, to_conf: bool) {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            RESTART_TO_CONF = to_conf;
 | 
			
		||||
            if to_conf {
 | 
			
		||||
                RESTART_TO_CONF = 1;
 | 
			
		||||
            } else {
 | 
			
		||||
                RESTART_TO_CONF = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -374,10 +374,9 @@ impl Esp<'_> {
 | 
			
		||||
        //unsafe {
 | 
			
		||||
        // //allow early wakeup by pressing the boot button
 | 
			
		||||
        if duration_in_ms == 0 {
 | 
			
		||||
            loop {
 | 
			
		||||
                info!("todo reboot")
 | 
			
		||||
            }
 | 
			
		||||
            software_reset();
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
            loop {
 | 
			
		||||
                info!("todo deepsleep")
 | 
			
		||||
            }
 | 
			
		||||
@@ -547,31 +546,34 @@ impl Esp<'_> {
 | 
			
		||||
            unsafe {
 | 
			
		||||
                LAST_WATERING_TIMESTAMP = [0; PLANT_COUNT];
 | 
			
		||||
                CONSECUTIVE_WATERING_PLANT = [0; PLANT_COUNT];
 | 
			
		||||
                LOW_VOLTAGE_DETECTED = false;
 | 
			
		||||
                crate::log::init().await;
 | 
			
		||||
                RESTART_TO_CONF = to_config_mode;
 | 
			
		||||
                LOW_VOLTAGE_DETECTED = 0;
 | 
			
		||||
                if to_config_mode {
 | 
			
		||||
                    RESTART_TO_CONF = 1
 | 
			
		||||
                } else {
 | 
			
		||||
                    RESTART_TO_CONF = 0;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        } else {
 | 
			
		||||
            unsafe {
 | 
			
		||||
                if to_config_mode {
 | 
			
		||||
                    RESTART_TO_CONF = true;
 | 
			
		||||
                    RESTART_TO_CONF = 1;
 | 
			
		||||
                }
 | 
			
		||||
                log(
 | 
			
		||||
                LOG_ACCESS.lock().await.log(
 | 
			
		||||
                    LogMessage::RestartToConfig,
 | 
			
		||||
                    RESTART_TO_CONF as u32,
 | 
			
		||||
                    0,
 | 
			
		||||
                    "",
 | 
			
		||||
                    "",
 | 
			
		||||
                )
 | 
			
		||||
                .await;
 | 
			
		||||
                log(
 | 
			
		||||
                ).await
 | 
			
		||||
                ;
 | 
			
		||||
                LOG_ACCESS.lock().await.log(
 | 
			
		||||
                    LogMessage::LowVoltage,
 | 
			
		||||
                    LOW_VOLTAGE_DETECTED as u32,
 | 
			
		||||
                    0,
 | 
			
		||||
                    "",
 | 
			
		||||
                    "",
 | 
			
		||||
                )
 | 
			
		||||
                .await;
 | 
			
		||||
                ).await
 | 
			
		||||
                ;
 | 
			
		||||
                for i in 0..PLANT_COUNT {
 | 
			
		||||
                    log::info!(
 | 
			
		||||
                        "LAST_WATERING_TIMESTAMP[{}] = UTC {}",
 | 
			
		||||
 
 | 
			
		||||
@@ -18,13 +18,15 @@ use crate::{
 | 
			
		||||
        battery::{BatteryInteraction, NoBatteryMonitor},
 | 
			
		||||
        esp::Esp,
 | 
			
		||||
    },
 | 
			
		||||
    log::{log, LogMessage},
 | 
			
		||||
    log::{LogMessage},
 | 
			
		||||
};
 | 
			
		||||
use alloc::boxed::Box;
 | 
			
		||||
use alloc::format;
 | 
			
		||||
use alloc::sync::Arc;
 | 
			
		||||
use core::cell::OnceCell;
 | 
			
		||||
use anyhow::{bail, Ok, Result};
 | 
			
		||||
use async_trait::async_trait;
 | 
			
		||||
use chrono::{DateTime, FixedOffset, Utc};
 | 
			
		||||
use embassy_executor::Spawner;
 | 
			
		||||
//use battery::BQ34Z100G1;
 | 
			
		||||
//use bq34z100::Bq34z100g1Driver;
 | 
			
		||||
@@ -38,16 +40,22 @@ use measurements::{Current, Voltage};
 | 
			
		||||
 | 
			
		||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
 | 
			
		||||
use embassy_sync::mutex::Mutex;
 | 
			
		||||
use embassy_sync::once_lock::OnceLock;
 | 
			
		||||
use esp_alloc as _;
 | 
			
		||||
use esp_backtrace as _;
 | 
			
		||||
use esp_bootloader_esp_idf::ota::Slot;
 | 
			
		||||
use esp_hal::rng::Rng;
 | 
			
		||||
use esp_hal::rtc_cntl::{Rtc, SocResetReason};
 | 
			
		||||
use esp_hal::system::reset_reason;
 | 
			
		||||
use esp_hal::timer::timg::TimerGroup;
 | 
			
		||||
use esp_storage::FlashStorage;
 | 
			
		||||
use esp_wifi::{init, EspWifiController};
 | 
			
		||||
use littlefs2::fs::{Allocation, Filesystem as lfs2Filesystem};
 | 
			
		||||
use littlefs2::object_safe::DynStorage;
 | 
			
		||||
use log::{info, warn};
 | 
			
		||||
use crate::log::{LogArray, LOG_ACCESS};
 | 
			
		||||
 | 
			
		||||
pub static TIME_ACCESS: OnceLock<Rtc> = OnceLock::new();
 | 
			
		||||
 | 
			
		||||
//Only support for 8 right now!
 | 
			
		||||
pub const PLANT_COUNT: usize = 8;
 | 
			
		||||
@@ -181,6 +189,13 @@ impl PlantHal {
 | 
			
		||||
 | 
			
		||||
        esp_alloc::heap_allocator!(size: 64 * 1024);
 | 
			
		||||
        esp_alloc::heap_allocator!(#[link_section = ".dram2_uninit"] size: 64000);
 | 
			
		||||
 | 
			
		||||
        let rtc: Rtc = Rtc::new(peripherals.LPWR);
 | 
			
		||||
        match(TIME_ACCESS.init(rtc)){
 | 
			
		||||
            Result::Ok(_) => {}
 | 
			
		||||
            Err(_) => {}
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let systimer = SystemTimer::new(peripherals.SYSTIMER);
 | 
			
		||||
 | 
			
		||||
        let boot_button = Input::new(
 | 
			
		||||
@@ -335,36 +350,78 @@ impl PlantHal {
 | 
			
		||||
        //init,reset rtc memory depending on cause
 | 
			
		||||
        let mut init_rtc_store: bool = false;
 | 
			
		||||
        let mut to_config_mode: bool = false;
 | 
			
		||||
        let reasons = "";
 | 
			
		||||
        // let reasons = ResetReason::get();
 | 
			
		||||
        // match reasons {
 | 
			
		||||
        //     ResetReason::Software => {}
 | 
			
		||||
        //     ResetReason::ExternalPin => {}
 | 
			
		||||
        //     ResetReason::Watchdog => {
 | 
			
		||||
        //         init_rtc_store = true;
 | 
			
		||||
        //     }
 | 
			
		||||
        //     ResetReason::Sdio => init_rtc_store = true,
 | 
			
		||||
        //     ResetReason::Panic => init_rtc_store = true,
 | 
			
		||||
        //     ResetReason::InterruptWatchdog => init_rtc_store = true,
 | 
			
		||||
        //     ResetReason::PowerOn => init_rtc_store = true,
 | 
			
		||||
        //     ResetReason::Unknown => init_rtc_store = true,
 | 
			
		||||
        //     ResetReason::Brownout => init_rtc_store = true,
 | 
			
		||||
        //     ResetReason::TaskWatchdog => init_rtc_store = true,
 | 
			
		||||
        //     ResetReason::DeepSleep => {}
 | 
			
		||||
        //     ResetReason::USBPeripheral => {
 | 
			
		||||
        //         init_rtc_store = true;
 | 
			
		||||
        //         to_config_mode = true;
 | 
			
		||||
        //     }
 | 
			
		||||
        //     ResetReason::JTAG => init_rtc_store = true,
 | 
			
		||||
        // };
 | 
			
		||||
        log(
 | 
			
		||||
        let reasons = match reset_reason() {
 | 
			
		||||
            None => {
 | 
			
		||||
                "unknown"
 | 
			
		||||
            }
 | 
			
		||||
            Some(reason) => {
 | 
			
		||||
                match reason {
 | 
			
		||||
                    SocResetReason::ChipPowerOn => {
 | 
			
		||||
                        "power on"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreSw => {
 | 
			
		||||
                        "software reset"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreDeepSleep => {
 | 
			
		||||
                        "deep sleep"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreSDIO => {
 | 
			
		||||
                        "sdio reset"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreMwdt0 => {
 | 
			
		||||
                        "Watchdog Main"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreMwdt1 => {
 | 
			
		||||
                        "Watchdog 1"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreRtcWdt => {
 | 
			
		||||
                        "Watchdog RTC"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::Cpu0Mwdt0 => {
 | 
			
		||||
                        "Watchdog MCpu0"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::Cpu0Sw => {
 | 
			
		||||
                        "software reset cpu0"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::Cpu0RtcWdt => {
 | 
			
		||||
                        init_rtc_store = true;
 | 
			
		||||
                        "Watchdog RTC cpu0"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::SysBrownOut => {
 | 
			
		||||
                        "sys brown out"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::SysRtcWdt => {
 | 
			
		||||
                        "Watchdog Sys rtc"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::Cpu0Mwdt1 => {
 | 
			
		||||
                        "cpu0 mwdt1"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::SysSuperWdt => {
 | 
			
		||||
                        "Watchdog Super"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreEfuseCrc => {
 | 
			
		||||
                        "core efuse crc"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreUsbUart => {
 | 
			
		||||
                        to_config_mode = true;
 | 
			
		||||
                        "core usb uart"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::CoreUsbJtag => {
 | 
			
		||||
                        "core usb jtag"
 | 
			
		||||
                    }
 | 
			
		||||
                    SocResetReason::Cpu0JtagCpu => {
 | 
			
		||||
                        "cpu0 jtag cpu"
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        LOG_ACCESS.lock().await.log(
 | 
			
		||||
            LogMessage::ResetReason,
 | 
			
		||||
            init_rtc_store as u32,
 | 
			
		||||
            to_config_mode as u32,
 | 
			
		||||
            "",
 | 
			
		||||
            &format!("{reasons:?}"),
 | 
			
		||||
        )
 | 
			
		||||
        .await;
 | 
			
		||||
        ).await;
 | 
			
		||||
 | 
			
		||||
        esp.init_rtc_deepsleep_memory(init_rtc_store, to_config_mode)
 | 
			
		||||
            .await;
 | 
			
		||||
@@ -430,32 +487,32 @@ impl PlantHal {
 | 
			
		||||
                        }
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                let board_hal: Box<dyn BoardInteraction + Send> = match config.hardware.board {
 | 
			
		||||
                    BoardVersion::INITIAL => {
 | 
			
		||||
                let board_hal: Box<dyn BoardInteraction + Send> = //match config.hardware.board {
 | 
			
		||||
                    //BoardVersion::INITIAL => {
 | 
			
		||||
                        initial_hal::create_initial_board(free_pins, config, esp)?
 | 
			
		||||
                    }
 | 
			
		||||
                ;
 | 
			
		||||
                        //}
 | 
			
		||||
                    // BoardVersion::V3 => {
 | 
			
		||||
                    //     v3_hal::create_v3(free_pins, esp, config, battery_interaction, rtc_module)?
 | 
			
		||||
                    // }
 | 
			
		||||
                    // BoardVersion::V4 => {
 | 
			
		||||
                    //     v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)?
 | 
			
		||||
                    // }
 | 
			
		||||
                    _ => {
 | 
			
		||||
                        todo!()
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                    //BoardVersion::V4 => {
 | 
			
		||||
                    //    v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)?
 | 
			
		||||
                    //}
 | 
			
		||||
                    //_ => {
 | 
			
		||||
                    //    todo!()
 | 
			
		||||
                    //}
 | 
			
		||||
                //};
 | 
			
		||||
 | 
			
		||||
                HAL { board_hal }
 | 
			
		||||
            }
 | 
			
		||||
            Err(err) => {
 | 
			
		||||
                log(
 | 
			
		||||
                LOG_ACCESS.lock().await.log(
 | 
			
		||||
                    LogMessage::ConfigModeMissingConfig,
 | 
			
		||||
                    0,
 | 
			
		||||
                    0,
 | 
			
		||||
                    "",
 | 
			
		||||
                    &err.to_string(),
 | 
			
		||||
                )
 | 
			
		||||
                .await;
 | 
			
		||||
                ).await;
 | 
			
		||||
                HAL {
 | 
			
		||||
                    board_hal: initial_hal::create_initial_board(
 | 
			
		||||
                        free_pins,
 | 
			
		||||
@@ -469,3 +526,12 @@ impl PlantHal {
 | 
			
		||||
        Ok(Mutex::new(hal))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pub async fn esp_time() -> DateTime<Utc> {
 | 
			
		||||
    DateTime::from_timestamp_micros(TIME_ACCESS.get().await.current_time_us() as i64).unwrap()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn esp_set_time(time: DateTime<FixedOffset>) {
 | 
			
		||||
    TIME_ACCESS.get().await.set_current_time_us(time.timestamp_micros() as u64);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,47 +1,122 @@
 | 
			
		||||
use crate::vec;
 | 
			
		||||
use alloc::string::ToString;
 | 
			
		||||
use alloc::vec::Vec;
 | 
			
		||||
use bytemuck::{AnyBitPattern, Contiguous, Pod, Zeroable};
 | 
			
		||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
 | 
			
		||||
use embassy_sync::lazy_lock::LazyLock;
 | 
			
		||||
use embassy_sync::mutex::Mutex;
 | 
			
		||||
use embassy_time::Instant;
 | 
			
		||||
use esp_println::println;
 | 
			
		||||
use esp_hal::Persistable;
 | 
			
		||||
use log::info;
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
use strum_macros::IntoStaticStr;
 | 
			
		||||
 | 
			
		||||
use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
 | 
			
		||||
use unit_enum::UnitEnum;
 | 
			
		||||
use crate::hal::TIME_ACCESS;
 | 
			
		||||
 | 
			
		||||
#[esp_hal::ram(rtc_fast, persistent)]
 | 
			
		||||
static mut LOG_ARRAY: LogArray = LogArray {
 | 
			
		||||
    buffer: [LogEntryInner { timestamp: 0, message_id: 0, a: 0, b: 0, txt_short: [0;TXT_SHORT_LENGTH], txt_long: [0;TXT_LONG_LENGTH] }; 256],
 | 
			
		||||
    head: 0,
 | 
			
		||||
};
 | 
			
		||||
pub static LOG_ACCESS: Mutex<CriticalSectionRawMutex, LogArray> = Mutex::new(unsafe { LOG_ARRAY });
 | 
			
		||||
 | 
			
		||||
const TXT_SHORT_LENGTH: usize = 8;
 | 
			
		||||
const TXT_LONG_LENGTH: usize = 32;
 | 
			
		||||
 | 
			
		||||
const BUFFER_SIZE: usize = 220;
 | 
			
		||||
 | 
			
		||||
#[link_section = ".rtc.data"]
 | 
			
		||||
static mut BUFFER: ConstGenericRingBuffer<LogEntry, BUFFER_SIZE> =
 | 
			
		||||
    ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
 | 
			
		||||
#[allow(static_mut_refs)]
 | 
			
		||||
static BUFFER_ACCESS: LazyLock<
 | 
			
		||||
    Mutex<CriticalSectionRawMutex, &mut ConstGenericRingBuffer<LogEntry, BUFFER_SIZE>>,
 | 
			
		||||
> = LazyLock::new(|| unsafe { Mutex::new(&mut BUFFER) });
 | 
			
		||||
#[derive(Debug, Clone, Copy, AnyBitPattern)]
 | 
			
		||||
#[repr(C)]
 | 
			
		||||
pub struct LogArray{
 | 
			
		||||
    buffer: [LogEntryInner; (u8::MAX_VALUE  as usize) +1],
 | 
			
		||||
    head: u8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Debug, Clone)]
 | 
			
		||||
unsafe impl Persistable for LogArray {}
 | 
			
		||||
unsafe impl Zeroable for LogEntryInner {}
 | 
			
		||||
 | 
			
		||||
unsafe impl Pod for LogEntryInner{}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, Copy)]
 | 
			
		||||
struct LogEntryInner {
 | 
			
		||||
    pub timestamp: u64,
 | 
			
		||||
    pub message_id: u16,
 | 
			
		||||
    pub a: u32,
 | 
			
		||||
    pub b: u32,
 | 
			
		||||
    pub txt_short: [u8; TXT_SHORT_LENGTH],
 | 
			
		||||
    pub txt_long: [u8; TXT_LONG_LENGTH],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize)]
 | 
			
		||||
pub struct LogEntry {
 | 
			
		||||
    pub timestamp: u64,
 | 
			
		||||
    pub message_id: u16,
 | 
			
		||||
    pub a: u32,
 | 
			
		||||
    pub b: u32,
 | 
			
		||||
    pub txt_short: heapless::String<TXT_SHORT_LENGTH>,
 | 
			
		||||
    pub txt_long: heapless::String<TXT_LONG_LENGTH>,
 | 
			
		||||
    pub txt_short: alloc::string::String,
 | 
			
		||||
    pub txt_long: alloc::string::String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn init() {
 | 
			
		||||
    unsafe {
 | 
			
		||||
        BUFFER = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
 | 
			
		||||
    };
 | 
			
		||||
    let mut access = BUFFER_ACCESS.get().lock().await;
 | 
			
		||||
    access.drain().for_each(|_| {});
 | 
			
		||||
impl From<LogEntryInner> for LogEntry {
 | 
			
		||||
    fn from(value: LogEntryInner) -> Self {
 | 
			
		||||
        LogEntry{
 | 
			
		||||
            timestamp: value.timestamp,
 | 
			
		||||
            message_id: value.message_id,
 | 
			
		||||
            a: value.a,
 | 
			
		||||
            b: value.b,
 | 
			
		||||
            txt_short: alloc::string::String::from_utf8_lossy_owned(value.txt_short.to_vec()),
 | 
			
		||||
            txt_long: alloc::string::String::from_utf8_lossy_owned(value.txt_long.to_vec()),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl LogArray {
 | 
			
		||||
    pub fn get(&mut self) -> Vec<LogEntry> {
 | 
			
		||||
        let mut rv: Vec<LogEntry> = Vec::new();
 | 
			
		||||
        let mut index = self.head.wrapping_sub(1);
 | 
			
		||||
        for _ in 0..self.buffer.len() {
 | 
			
		||||
            let entry = self.buffer[index as usize];
 | 
			
		||||
            if (entry.message_id as usize) != LogMessage::Empty.ordinal() {
 | 
			
		||||
                rv.push(entry.into());
 | 
			
		||||
            }
 | 
			
		||||
            index = index.wrapping_sub(1);
 | 
			
		||||
        }
 | 
			
		||||
        rv
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn log(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        message_key: LogMessage,
 | 
			
		||||
        number_a: u32,
 | 
			
		||||
        number_b: u32,
 | 
			
		||||
        txt_short: &str,
 | 
			
		||||
        txt_long: &str,
 | 
			
		||||
    ) {
 | 
			
		||||
        let mut txt_short_stack: heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
 | 
			
		||||
        let mut txt_long_stack: heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
 | 
			
		||||
 | 
			
		||||
        limit_length(txt_short, &mut txt_short_stack);
 | 
			
		||||
        limit_length(txt_long, &mut txt_long_stack);
 | 
			
		||||
 | 
			
		||||
        let time = TIME_ACCESS.get().await.current_time_us()/1000;
 | 
			
		||||
 | 
			
		||||
        let ordinal = message_key.ordinal() as u16;
 | 
			
		||||
        let template: &str = message_key.into();
 | 
			
		||||
        let mut template_string = template.to_string();
 | 
			
		||||
        template_string = template_string.replace("${number_a}", number_a.to_string().as_str());
 | 
			
		||||
        template_string = template_string.replace("${number_b}", number_b.to_string().as_str());
 | 
			
		||||
        template_string = template_string.replace("${txt_long}", txt_long);
 | 
			
		||||
        template_string = template_string.replace("${txt_short}", txt_short);
 | 
			
		||||
 | 
			
		||||
        info!("{}", template_string);
 | 
			
		||||
 | 
			
		||||
        let to_modify = &mut self.buffer[self.head as usize];
 | 
			
		||||
        to_modify.timestamp = time;
 | 
			
		||||
        to_modify.message_id = ordinal;
 | 
			
		||||
        to_modify.a = number_a;
 | 
			
		||||
        to_modify.b = number_b;
 | 
			
		||||
        to_modify.txt_short.clone_from_slice(&txt_short_stack.as_bytes());
 | 
			
		||||
        to_modify.txt_long.clone_from_slice(&txt_long_stack.as_bytes());
 | 
			
		||||
        self.head = self.head.wrapping_add(1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn limit_length<const LIMIT: usize>(input: &str, target: &mut heapless::String<LIMIT>) {
 | 
			
		||||
@@ -60,60 +135,19 @@ fn limit_length<const LIMIT: usize>(input: &str, target: &mut heapless::String<L
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn get_log() -> Vec<LogEntry> {
 | 
			
		||||
    let buffer = BUFFER_ACCESS.get().lock().await;
 | 
			
		||||
    let mut read_copy = Vec::new();
 | 
			
		||||
    for entry in buffer.iter() {
 | 
			
		||||
        let copy = entry.clone();
 | 
			
		||||
        read_copy.push(copy);
 | 
			
		||||
    while target.len() < LIMIT {
 | 
			
		||||
        target.push(' ').unwrap();
 | 
			
		||||
    }
 | 
			
		||||
    drop(buffer);
 | 
			
		||||
    read_copy
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub async fn log(
 | 
			
		||||
    message_key: LogMessage,
 | 
			
		||||
    number_a: u32,
 | 
			
		||||
    number_b: u32,
 | 
			
		||||
    txt_short: &str,
 | 
			
		||||
    txt_long: &str,
 | 
			
		||||
) {
 | 
			
		||||
    let mut txt_short_stack: heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
 | 
			
		||||
    let mut txt_long_stack: heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
 | 
			
		||||
 | 
			
		||||
    limit_length(txt_short, &mut txt_short_stack);
 | 
			
		||||
    limit_length(txt_long, &mut txt_long_stack);
 | 
			
		||||
 | 
			
		||||
    //TODO
 | 
			
		||||
    let time = Instant::now().as_secs();
 | 
			
		||||
    // let time = EspSystemTime {}.now().as_millis() as u64;
 | 
			
		||||
    //
 | 
			
		||||
    let ordinal = message_key.ordinal() as u16;
 | 
			
		||||
    let template: &str = message_key.into();
 | 
			
		||||
    let mut template_string = template.to_string();
 | 
			
		||||
    template_string = template_string.replace("${number_a}", number_a.to_string().as_str());
 | 
			
		||||
    template_string = template_string.replace("${number_b}", number_b.to_string().as_str());
 | 
			
		||||
    template_string = template_string.replace("${txt_long}", txt_long);
 | 
			
		||||
    template_string = template_string.replace("${txt_short}", txt_short);
 | 
			
		||||
 | 
			
		||||
    info!("LOG: {} : {}", time, template_string);
 | 
			
		||||
 | 
			
		||||
    let entry = LogEntry {
 | 
			
		||||
        timestamp: time,
 | 
			
		||||
        message_id: ordinal,
 | 
			
		||||
        a: number_a,
 | 
			
		||||
        b: number_b,
 | 
			
		||||
        txt_short: txt_short_stack,
 | 
			
		||||
        txt_long: txt_long_stack,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let mut buffer = BUFFER_ACCESS.get().lock().await;
 | 
			
		||||
    buffer.push(entry);
 | 
			
		||||
}
 | 
			
		||||
#[derive(IntoStaticStr, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone, UnitEnum)]
 | 
			
		||||
pub enum LogMessage {
 | 
			
		||||
    #[strum(
 | 
			
		||||
        serialize = ""
 | 
			
		||||
    )]
 | 
			
		||||
    Empty,
 | 
			
		||||
    #[strum(
 | 
			
		||||
        serialize = "Reset due to ${txt_long} requires rtc clear ${number_a} and force config mode ${number_b}"
 | 
			
		||||
    )]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
#![no_std]
 | 
			
		||||
#![no_main]
 | 
			
		||||
#![feature(never_type)]
 | 
			
		||||
#![feature(string_from_utf8_lossy_owned)]
 | 
			
		||||
#![deny(
 | 
			
		||||
    clippy::mem_forget,
 | 
			
		||||
    reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
 | 
			
		||||
@@ -35,9 +36,11 @@ use esp_hal::rom::ets_delay_us;
 | 
			
		||||
use esp_hal::system::software_reset;
 | 
			
		||||
use esp_println::{logger, println};
 | 
			
		||||
use hal::battery::BatteryState;
 | 
			
		||||
use log::{log, LogMessage};
 | 
			
		||||
use log::{ LogMessage};
 | 
			
		||||
use plant_state::PlantState;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use crate::hal::esp_time;
 | 
			
		||||
use crate::log::LOG_ACCESS;
 | 
			
		||||
 | 
			
		||||
#[no_mangle]
 | 
			
		||||
extern "C" fn custom_halt() -> ! {
 | 
			
		||||
@@ -180,6 +183,7 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
 | 
			
		||||
    let _ota_state_string = "unknown";
 | 
			
		||||
 | 
			
		||||
    board.board_hal.general_fault(false).await;
 | 
			
		||||
    let time = esp_time().await;
 | 
			
		||||
    let cur = board
 | 
			
		||||
        .board_hal
 | 
			
		||||
        .get_rtc_module()
 | 
			
		||||
@@ -188,19 +192,19 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
 | 
			
		||||
        .or_else(|err| {
 | 
			
		||||
            info!("rtc module error: {:?}", err);
 | 
			
		||||
            board.board_hal.general_fault(true);
 | 
			
		||||
            anyhow::Ok(board.board_hal.get_esp().time())
 | 
			
		||||
            anyhow::Ok(time)
 | 
			
		||||
        })?;
 | 
			
		||||
    //check if we know the time current > 2020 (plausibility checks, this code is newer than 2020)
 | 
			
		||||
    if cur.year() < 2020 {
 | 
			
		||||
        to_config = true;
 | 
			
		||||
        log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "").await;
 | 
			
		||||
        LOG_ACCESS.lock().await.log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "").await;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info!("cur is {}", cur);
 | 
			
		||||
    update_charge_indicator(&mut board).await;
 | 
			
		||||
    println!("faul led3");
 | 
			
		||||
    if board.board_hal.get_esp().get_restart_to_conf() {
 | 
			
		||||
        log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "").await;
 | 
			
		||||
        LOG_ACCESS.lock().await.log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "").await;
 | 
			
		||||
        for _i in 0..2 {
 | 
			
		||||
            board.board_hal.general_fault(true).await;
 | 
			
		||||
            Timer::after_millis(100).await;
 | 
			
		||||
@@ -212,7 +216,7 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
 | 
			
		||||
        board.board_hal.get_esp().set_restart_to_conf(false);
 | 
			
		||||
    } else if board.board_hal.get_esp().mode_override_pressed() {
 | 
			
		||||
        board.board_hal.general_fault(true).await;
 | 
			
		||||
        log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "").await;
 | 
			
		||||
        LOG_ACCESS.lock().await.log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "").await;
 | 
			
		||||
        for _i in 0..5 {
 | 
			
		||||
            board.board_hal.general_fault(true).await;
 | 
			
		||||
            Timer::after_millis(100).await;
 | 
			
		||||
@@ -293,7 +297,7 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
 | 
			
		||||
        let _ = publish_mppt_state(&mut board).await;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    log(
 | 
			
		||||
    LOG_ACCESS.lock().await.log(
 | 
			
		||||
        LogMessage::StartupInfo,
 | 
			
		||||
        matches!(network_mode, NetworkMode::WIFI { .. }) as u32,
 | 
			
		||||
        matches!(
 | 
			
		||||
@@ -307,8 +311,8 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
 | 
			
		||||
            .to_string()
 | 
			
		||||
            .as_str(),
 | 
			
		||||
        "",
 | 
			
		||||
    )
 | 
			
		||||
    .await;
 | 
			
		||||
    ).await
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
    if to_config {
 | 
			
		||||
        //check if client or ap mode and init Wi-Fi
 | 
			
		||||
@@ -319,7 +323,7 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
 | 
			
		||||
        let board = BOARD_ACCESS.get().await.lock().await;
 | 
			
		||||
        wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await;
 | 
			
		||||
    } else {
 | 
			
		||||
        log(LogMessage::NormalRun, 0, 0, "", "").await;
 | 
			
		||||
        LOG_ACCESS.lock().await.log(LogMessage::NormalRun, 0, 0, "", "").await;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let _dry_run = false;
 | 
			
		||||
@@ -658,14 +662,14 @@ pub async fn do_secure_pump(
 | 
			
		||||
                    let high_current = current_ma > plant_config.max_pump_current_ma;
 | 
			
		||||
                    if high_current {
 | 
			
		||||
                        if first_error {
 | 
			
		||||
                            log(
 | 
			
		||||
                            LOG_ACCESS.lock().await.log(
 | 
			
		||||
                                LogMessage::PumpOverCurrent,
 | 
			
		||||
                                plant_id as u32 + 1,
 | 
			
		||||
                                current_ma as u32,
 | 
			
		||||
                                plant_config.max_pump_current_ma.to_string().as_str(),
 | 
			
		||||
                                step.to_string().as_str(),
 | 
			
		||||
                            )
 | 
			
		||||
                            .await;
 | 
			
		||||
                            ).await
 | 
			
		||||
                            ;
 | 
			
		||||
                            board.board_hal.general_fault(true).await;
 | 
			
		||||
                            board.board_hal.fault(plant_id, true).await?;
 | 
			
		||||
                            if !plant_config.ignore_current_error {
 | 
			
		||||
@@ -678,14 +682,14 @@ pub async fn do_secure_pump(
 | 
			
		||||
                    let low_current = current_ma < plant_config.min_pump_current_ma;
 | 
			
		||||
                    if low_current {
 | 
			
		||||
                        if first_error {
 | 
			
		||||
                            log(
 | 
			
		||||
                            LOG_ACCESS.lock().await.log(
 | 
			
		||||
                                LogMessage::PumpOpenLoopCurrent,
 | 
			
		||||
                                plant_id as u32 + 1,
 | 
			
		||||
                                current_ma as u32,
 | 
			
		||||
                                plant_config.min_pump_current_ma.to_string().as_str(),
 | 
			
		||||
                                step.to_string().as_str(),
 | 
			
		||||
                            )
 | 
			
		||||
                            .await;
 | 
			
		||||
                            ).await
 | 
			
		||||
                            ;
 | 
			
		||||
                            board.board_hal.general_fault(true).await;
 | 
			
		||||
                            board.board_hal.fault(plant_id, true).await?;
 | 
			
		||||
                            if !plant_config.ignore_current_error {
 | 
			
		||||
@@ -699,14 +703,14 @@ pub async fn do_secure_pump(
 | 
			
		||||
                Err(err) => {
 | 
			
		||||
                    if !plant_config.ignore_current_error {
 | 
			
		||||
                        info!("Error getting pump current: {}", err);
 | 
			
		||||
                        log(
 | 
			
		||||
                        LOG_ACCESS.lock().await.log(
 | 
			
		||||
                            LogMessage::PumpMissingSensorCurrent,
 | 
			
		||||
                            plant_id as u32,
 | 
			
		||||
                            0,
 | 
			
		||||
                            "",
 | 
			
		||||
                            "",
 | 
			
		||||
                        )
 | 
			
		||||
                        .await;
 | 
			
		||||
                        ).await
 | 
			
		||||
                        ;
 | 
			
		||||
                        error = true;
 | 
			
		||||
                        break;
 | 
			
		||||
                    } else {
 | 
			
		||||
@@ -1058,7 +1062,7 @@ async fn wait_infinity(
 | 
			
		||||
                .lock()
 | 
			
		||||
                .await
 | 
			
		||||
                .board_hal
 | 
			
		||||
                .deep_sleep(1);
 | 
			
		||||
                .deep_sleep(0).await;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,29 +3,30 @@
 | 
			
		||||
use crate::config::PlantControllerConfig;
 | 
			
		||||
use crate::{get_version, log::LogMessage, BOARD_ACCESS};
 | 
			
		||||
use alloc::borrow::ToOwned;
 | 
			
		||||
use alloc::fmt::format;
 | 
			
		||||
use alloc::format;
 | 
			
		||||
use alloc::string::{String, ToString};
 | 
			
		||||
use alloc::sync::Arc;
 | 
			
		||||
use alloc::vec::Vec;
 | 
			
		||||
use anyhow::bail;
 | 
			
		||||
use anyhow::{bail};
 | 
			
		||||
use core::fmt::{Debug, Display};
 | 
			
		||||
use core::net::{IpAddr, Ipv4Addr, SocketAddr};
 | 
			
		||||
use core::result::Result::Ok;
 | 
			
		||||
use core::str::from_utf8;
 | 
			
		||||
use core::sync::atomic::{AtomicBool, Ordering};
 | 
			
		||||
use chrono::DateTime;
 | 
			
		||||
use edge_http::io::server::{Connection, Handler, Server};
 | 
			
		||||
use edge_http::io::Error;
 | 
			
		||||
use edge_http::Method;
 | 
			
		||||
use edge_nal::{TcpBind, TcpSplit};
 | 
			
		||||
use edge_nal::{TcpBind};
 | 
			
		||||
use edge_nal_embassy::{Tcp, TcpBuffers};
 | 
			
		||||
use embassy_net::Stack;
 | 
			
		||||
use embassy_time::Instant;
 | 
			
		||||
use embedded_io_async::{Read, Write};
 | 
			
		||||
use esp_println::println;
 | 
			
		||||
use littlefs2_core::Path;
 | 
			
		||||
use log::info;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use crate::hal::{esp_set_time, esp_time};
 | 
			
		||||
use crate::log::{LOG_ACCESS};
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Debug)]
 | 
			
		||||
struct SSIDList {
 | 
			
		||||
@@ -72,25 +73,6 @@ pub struct NightLampCommand {
 | 
			
		||||
    active: bool,
 | 
			
		||||
}
 | 
			
		||||
//
 | 
			
		||||
// fn write_time(
 | 
			
		||||
//     request: &mut Request<&mut EspHttpConnection>,
 | 
			
		||||
// ) -> Result<Option<std::string::String>, anyhow::Error> {
 | 
			
		||||
//     let actual_data = read_up_to_bytes_from_request(request, None)?;
 | 
			
		||||
//     let time: SetTime = serde_json::from_slice(&actual_data)?;
 | 
			
		||||
//     let parsed = DateTime::parse_from_rfc3339(time.time).map_err(|err| anyhow::anyhow!(err))?;
 | 
			
		||||
//     let mut board = BOARD_ACCESS.lock().expect("board access");
 | 
			
		||||
//
 | 
			
		||||
//     let now = timeval {
 | 
			
		||||
//         tv_sec: parsed.to_utc().timestamp(),
 | 
			
		||||
//         tv_usec: 0,
 | 
			
		||||
//     };
 | 
			
		||||
//     unsafe { settimeofday(&now, core::ptr::null_mut()) };
 | 
			
		||||
//     board
 | 
			
		||||
//         .board_hal
 | 
			
		||||
//         .get_rtc_module()
 | 
			
		||||
//         .set_rtc_time(&parsed.to_utc())?;
 | 
			
		||||
//     anyhow::Ok(None)
 | 
			
		||||
// }
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
@@ -430,12 +412,10 @@ impl Handler for HttpHandler {
 | 
			
		||||
                        conn.write_all(include_bytes!("bundle.js")).await?;
 | 
			
		||||
                        Some(200)
 | 
			
		||||
                    }
 | 
			
		||||
                    "/reboot" => {
 | 
			
		||||
                        let mut board = BOARD_ACCESS.get().await.lock().await;
 | 
			
		||||
                        board.board_hal.get_esp().set_restart_to_conf(true);
 | 
			
		||||
                        self.reboot_now.store(true, Ordering::Relaxed);
 | 
			
		||||
                    "/log" => {
 | 
			
		||||
                        let buf = get_log(conn).await;
 | 
			
		||||
                        Some(200)
 | 
			
		||||
                    }
 | 
			
		||||
                    },
 | 
			
		||||
                    &_ => {
 | 
			
		||||
                        let json = match path {
 | 
			
		||||
                            "/version" => Some(get_version_web(conn).await),
 | 
			
		||||
@@ -445,7 +425,6 @@ impl Handler for HttpHandler {
 | 
			
		||||
                            "/get_config" => Some(get_config(conn).await),
 | 
			
		||||
                            "/files" => Some(list_files(conn).await),
 | 
			
		||||
                            "/log_localization" => Some(get_log_localization_config(conn).await),
 | 
			
		||||
                            "/log" => Some(get_log(conn).await),
 | 
			
		||||
                            "/wifiscan" => Some(wifi_scan(conn).await),
 | 
			
		||||
                            _ => None,
 | 
			
		||||
                        };
 | 
			
		||||
@@ -459,6 +438,13 @@ impl Handler for HttpHandler {
 | 
			
		||||
                    let json = match path {
 | 
			
		||||
                        "/wifiscan" => Some(wifi_scan(conn).await),
 | 
			
		||||
                        "/set_config" => Some(set_config(conn).await),
 | 
			
		||||
                        "/time" => Some(write_time(conn).await),
 | 
			
		||||
                        "/reboot" => {
 | 
			
		||||
                            let mut board = BOARD_ACCESS.get().await.lock().await;
 | 
			
		||||
                            board.board_hal.get_esp().set_restart_to_conf(true);
 | 
			
		||||
                            self.reboot_now.store(true, Ordering::Relaxed);
 | 
			
		||||
                            Some(Ok(None))
 | 
			
		||||
                        }
 | 
			
		||||
                        _ => None,
 | 
			
		||||
                    };
 | 
			
		||||
                    match json {
 | 
			
		||||
@@ -568,6 +554,20 @@ impl Handler for HttpHandler {
 | 
			
		||||
//     })
 | 
			
		||||
//     .unwrap();
 | 
			
		||||
 | 
			
		||||
async fn write_time<T, const N: usize>(
 | 
			
		||||
    request: &mut Connection<'_, T, N>,
 | 
			
		||||
) -> Result<Option<String>, anyhow::Error>
 | 
			
		||||
where
 | 
			
		||||
    T: Read + Write
 | 
			
		||||
{
 | 
			
		||||
    let actual_data = read_up_to_bytes_from_request(request, None).await?;
 | 
			
		||||
    let time: SetTime = serde_json::from_slice(&actual_data)?;
 | 
			
		||||
    let parsed = DateTime::parse_from_rfc3339(time.time).unwrap();
 | 
			
		||||
    esp_set_time(parsed).await;
 | 
			
		||||
    anyhow::Ok(None)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async fn set_config<T, const N: usize>(
 | 
			
		||||
    request: &mut Connection<'_, T, N>,
 | 
			
		||||
) -> Result<Option<String>, anyhow::Error>
 | 
			
		||||
@@ -633,10 +633,30 @@ async fn wifi_scan<T, const N: usize>(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn get_log<T, const N: usize>(
 | 
			
		||||
    _request: &mut Connection<'_, T, N>,
 | 
			
		||||
) -> Result<Option<String>, anyhow::Error> {
 | 
			
		||||
    let output = crate::log::get_log().await;
 | 
			
		||||
    anyhow::Ok(Some(serde_json::to_string(&output)?))
 | 
			
		||||
    conn: &mut Connection<'_, T, N>,
 | 
			
		||||
) -> anyhow::Result<()>
 | 
			
		||||
where
 | 
			
		||||
    T: Read + Write,{
 | 
			
		||||
    let log = LOG_ACCESS.lock().await.get();
 | 
			
		||||
    conn.initiate_response(
 | 
			
		||||
        200,
 | 
			
		||||
        Some("OK"),
 | 
			
		||||
        &[("Content-Type", "text/javascript")],
 | 
			
		||||
    )
 | 
			
		||||
        .await
 | 
			
		||||
        .unwrap();
 | 
			
		||||
    conn.write_all("[".as_bytes()).await.unwrap();
 | 
			
		||||
    let mut append = false;
 | 
			
		||||
    for  entry in log {
 | 
			
		||||
        if append {
 | 
			
		||||
            conn.write_all(",".as_bytes()).await.unwrap();
 | 
			
		||||
        }
 | 
			
		||||
        append = true;
 | 
			
		||||
        let json = serde_json::to_string(&entry)?;
 | 
			
		||||
        conn.write_all(json.as_bytes()).await.unwrap();
 | 
			
		||||
    }
 | 
			
		||||
    conn.write_all("]".as_bytes()).await.unwrap();
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async fn get_log_localization_config<T, const N: usize>(
 | 
			
		||||
@@ -698,16 +718,17 @@ async fn get_time<T, const N: usize>(
 | 
			
		||||
) -> Result<Option<String>, anyhow::Error> {
 | 
			
		||||
    let mut board = BOARD_ACCESS.get().await.lock().await;
 | 
			
		||||
    //TODO do not fail if rtc module is missing
 | 
			
		||||
    let native = board.board_hal.get_esp().time().to_rfc3339();
 | 
			
		||||
    let rtc = board
 | 
			
		||||
        .board_hal
 | 
			
		||||
        .get_rtc_module()
 | 
			
		||||
        .get_rtc_time()
 | 
			
		||||
        .await?
 | 
			
		||||
        .to_rfc3339();
 | 
			
		||||
    let native = esp_time().await.to_rfc3339();
 | 
			
		||||
    let rtc = "todo";
 | 
			
		||||
    // board
 | 
			
		||||
    //     .board_hal
 | 
			
		||||
    //     .get_rtc_module()
 | 
			
		||||
    //     .get_rtc_time()
 | 
			
		||||
    //     .await?
 | 
			
		||||
    //     .to_rfc3339();
 | 
			
		||||
 | 
			
		||||
    let data = LoadData {
 | 
			
		||||
        rtc: rtc.as_str(),
 | 
			
		||||
        rtc,
 | 
			
		||||
        native: native.as_str(),
 | 
			
		||||
    };
 | 
			
		||||
    let json = serde_json::to_string(&data)?;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user