get log to work, make time accessible
This commit is contained in:
parent
584d6df2d0
commit
c94f5bdb45
@ -133,16 +133,11 @@ serde = { version = "1.0.219", features = ["derive", "alloc"], default-features
|
|||||||
serde_json = { version = "1.0.143", default-features = false, features = ["alloc"] }
|
serde_json = { version = "1.0.143", default-features = false, features = ["alloc"] }
|
||||||
|
|
||||||
#timezone
|
#timezone
|
||||||
|
|
||||||
chrono = { version = "0.4.42", default-features = false, features = ["iana-time-zone", "alloc", "serde"] }
|
chrono = { version = "0.4.42", default-features = false, features = ["iana-time-zone", "alloc", "serde"] }
|
||||||
chrono-tz = { version = "0.10.4", default-features = false, features = ["filter-by-regex"] }
|
chrono-tz = { version = "0.10.4", default-features = false, features = ["filter-by-regex"] }
|
||||||
eeprom24x = "0.7.2"
|
eeprom24x = "0.7.2"
|
||||||
#url = "2.5.3"
|
|
||||||
crc = "3.2.1"
|
crc = "3.2.1"
|
||||||
bincode = { version = "2.0.1", default-features = false, features = ["alloc", "serde"] }
|
|
||||||
ringbuffer = "0.15.0"
|
|
||||||
strum_macros = "0.27.0"
|
strum_macros = "0.27.0"
|
||||||
#esp-ota = { version = "0.2.2", features = ["log"] }
|
|
||||||
unit-enum = "1.4.1"
|
unit-enum = "1.4.1"
|
||||||
pca9535 = { version = "2.0.0" }
|
pca9535 = { version = "2.0.0" }
|
||||||
ina219 = { version = "0.2.0" }
|
ina219 = { version = "0.2.0" }
|
||||||
@ -157,10 +152,10 @@ edge-dhcp = "0.6.0"
|
|||||||
edge-nal = "0.5.0"
|
edge-nal = "0.5.0"
|
||||||
edge-nal-embassy = "0.6.0"
|
edge-nal-embassy = "0.6.0"
|
||||||
static_cell = "2.1.1"
|
static_cell = "2.1.1"
|
||||||
cfg-if = "1.0.3"
|
|
||||||
edge-http = { version = "0.6.1", features = ["log"] }
|
edge-http = { version = "0.6.1", features = ["log"] }
|
||||||
littlefs2 = { version = "0.6.1", features = ["c-stubs", "alloc"] }
|
littlefs2 = { version = "0.6.1", features = ["c-stubs", "alloc"] }
|
||||||
littlefs2-core = "0.1.1"
|
littlefs2-core = "0.1.1"
|
||||||
|
bytemuck = { version = "1.23.2", features = ["derive", "min_const_generics", "pod_saturating", "extern_crate_alloc"] }
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use crate::config::{NetworkConfig, PlantControllerConfig};
|
use crate::config::{NetworkConfig, PlantControllerConfig};
|
||||||
use crate::hal::{GW_IP_ADDR_ENV, PLANT_COUNT};
|
use crate::hal::{GW_IP_ADDR_ENV, PLANT_COUNT, TIME_ACCESS};
|
||||||
use crate::log::{log, LogMessage};
|
use crate::log::{ LogArray, LogMessage, LOG_ACCESS};
|
||||||
use crate::STAY_ALIVE;
|
use crate::STAY_ALIVE;
|
||||||
use anyhow::{anyhow, bail, Context};
|
use anyhow::{anyhow, bail, Context};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, FixedOffset, Utc};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
||||||
@ -13,12 +13,10 @@ use alloc::{format, string::String, vec::Vec};
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::net::{IpAddr, Ipv4Addr};
|
use core::net::{IpAddr, Ipv4Addr};
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use embassy_executor::{SendSpawner, Spawner};
|
use embassy_executor::{Spawner};
|
||||||
use embassy_net::tcp::TcpSocket;
|
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||||
use embassy_net::{IpListenEndpoint, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::rwlock::TryLockError;
|
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
use embedded_storage::nor_flash::ReadNorFlash;
|
use embedded_storage::nor_flash::ReadNorFlash;
|
||||||
use embedded_storage::Storage;
|
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_bootloader_esp_idf::partitions::{Error, FlashRegion, PartitionEntry, PartitionTable};
|
||||||
use esp_hal::gpio::Input;
|
use esp_hal::gpio::Input;
|
||||||
use esp_hal::rng::Rng;
|
use esp_hal::rng::Rng;
|
||||||
|
use esp_hal::rtc_cntl::Rtc;
|
||||||
use esp_hal::rtc_cntl::sleep::RtcSleepConfig;
|
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_storage::FlashStorage;
|
||||||
use esp_wifi::wifi::{
|
use esp_wifi::wifi::{
|
||||||
AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
|
AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
|
||||||
ScanTypeConfig, WifiController, WifiDevice, WifiEvent, WifiState,
|
ScanTypeConfig, WifiController, WifiDevice,
|
||||||
};
|
};
|
||||||
use littlefs2::fs::Filesystem;
|
use littlefs2::fs::Filesystem;
|
||||||
use littlefs2_core::{DynFile, FileType, OpenSeekFrom, Path, PathBuf, SeekFrom};
|
use littlefs2_core::{DynFile, FileType, PathBuf, SeekFrom};
|
||||||
use log::{info, warn};
|
use log::{info};
|
||||||
|
|
||||||
#[link_section = ".rtc.data"]
|
#[esp_hal::ram(rtc_fast, persistent)]
|
||||||
static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT];
|
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];
|
static mut CONSECUTIVE_WATERING_PLANT: [u32; PLANT_COUNT] = [0; PLANT_COUNT];
|
||||||
#[link_section = ".rtc.data"]
|
#[esp_hal::ram(rtc_fast, persistent)]
|
||||||
static mut LOW_VOLTAGE_DETECTED: bool = false;
|
static mut LOW_VOLTAGE_DETECTED: i8 = 0;
|
||||||
#[link_section = ".rtc.data"]
|
#[esp_hal::ram(rtc_fast, persistent)]
|
||||||
static mut RESTART_TO_CONF: bool = false;
|
static mut RESTART_TO_CONF: i8 = 0;
|
||||||
|
|
||||||
static CONFIG_FILE: &str = "config.json";
|
static CONFIG_FILE: &str = "config.json";
|
||||||
|
|
||||||
@ -239,10 +239,6 @@ impl Esp<'_> {
|
|||||||
bail!("not implemented")
|
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>> {
|
pub(crate) async fn wifi_scan(&mut self) -> anyhow::Result<Vec<AccessPointInfo>> {
|
||||||
info!("start wifi scan");
|
info!("start wifi scan");
|
||||||
@ -277,17 +273,17 @@ impl Esp<'_> {
|
|||||||
}
|
}
|
||||||
pub(crate) fn set_low_voltage_in_cycle(&mut self) {
|
pub(crate) fn set_low_voltage_in_cycle(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
LOW_VOLTAGE_DETECTED = true;
|
LOW_VOLTAGE_DETECTED = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn clear_low_voltage_in_cycle(&mut self) {
|
pub(crate) fn clear_low_voltage_in_cycle(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
LOW_VOLTAGE_DETECTED = false;
|
LOW_VOLTAGE_DETECTED = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn low_voltage_in_cycle(&mut self) -> bool {
|
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) {
|
pub(crate) fn store_consecutive_pump_count(&mut self, plant: usize, count: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -298,11 +294,15 @@ impl Esp<'_> {
|
|||||||
unsafe { CONSECUTIVE_WATERING_PLANT[plant] }
|
unsafe { CONSECUTIVE_WATERING_PLANT[plant] }
|
||||||
}
|
}
|
||||||
pub(crate) fn get_restart_to_conf(&mut self) -> bool {
|
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) {
|
pub(crate) fn set_restart_to_conf(&mut self, to_conf: bool) {
|
||||||
unsafe {
|
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 {
|
//unsafe {
|
||||||
// //allow early wakeup by pressing the boot button
|
// //allow early wakeup by pressing the boot button
|
||||||
if duration_in_ms == 0 {
|
if duration_in_ms == 0 {
|
||||||
loop {
|
software_reset();
|
||||||
info!("todo reboot")
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
info!("todo deepsleep")
|
info!("todo deepsleep")
|
||||||
}
|
}
|
||||||
@ -547,31 +546,34 @@ impl Esp<'_> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
LAST_WATERING_TIMESTAMP = [0; PLANT_COUNT];
|
LAST_WATERING_TIMESTAMP = [0; PLANT_COUNT];
|
||||||
CONSECUTIVE_WATERING_PLANT = [0; PLANT_COUNT];
|
CONSECUTIVE_WATERING_PLANT = [0; PLANT_COUNT];
|
||||||
LOW_VOLTAGE_DETECTED = false;
|
LOW_VOLTAGE_DETECTED = 0;
|
||||||
crate::log::init().await;
|
if to_config_mode {
|
||||||
RESTART_TO_CONF = to_config_mode;
|
RESTART_TO_CONF = 1
|
||||||
|
} else {
|
||||||
|
RESTART_TO_CONF = 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
if to_config_mode {
|
if to_config_mode {
|
||||||
RESTART_TO_CONF = true;
|
RESTART_TO_CONF = 1;
|
||||||
}
|
}
|
||||||
log(
|
LOG_ACCESS.lock().await.log(
|
||||||
LogMessage::RestartToConfig,
|
LogMessage::RestartToConfig,
|
||||||
RESTART_TO_CONF as u32,
|
RESTART_TO_CONF as u32,
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
)
|
).await
|
||||||
.await;
|
;
|
||||||
log(
|
LOG_ACCESS.lock().await.log(
|
||||||
LogMessage::LowVoltage,
|
LogMessage::LowVoltage,
|
||||||
LOW_VOLTAGE_DETECTED as u32,
|
LOW_VOLTAGE_DETECTED as u32,
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
)
|
).await
|
||||||
.await;
|
;
|
||||||
for i in 0..PLANT_COUNT {
|
for i in 0..PLANT_COUNT {
|
||||||
log::info!(
|
log::info!(
|
||||||
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
|
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
|
||||||
|
@ -18,13 +18,15 @@ use crate::{
|
|||||||
battery::{BatteryInteraction, NoBatteryMonitor},
|
battery::{BatteryInteraction, NoBatteryMonitor},
|
||||||
esp::Esp,
|
esp::Esp,
|
||||||
},
|
},
|
||||||
log::{log, LogMessage},
|
log::{LogMessage},
|
||||||
};
|
};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
|
use core::cell::OnceCell;
|
||||||
use anyhow::{bail, Ok, Result};
|
use anyhow::{bail, Ok, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use chrono::{DateTime, FixedOffset, Utc};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
//use battery::BQ34Z100G1;
|
//use battery::BQ34Z100G1;
|
||||||
//use bq34z100::Bq34z100g1Driver;
|
//use bq34z100::Bq34z100g1Driver;
|
||||||
@ -38,16 +40,22 @@ use measurements::{Current, Voltage};
|
|||||||
|
|
||||||
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
|
use embassy_sync::once_lock::OnceLock;
|
||||||
use esp_alloc as _;
|
use esp_alloc as _;
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_bootloader_esp_idf::ota::Slot;
|
use esp_bootloader_esp_idf::ota::Slot;
|
||||||
use esp_hal::rng::Rng;
|
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_hal::timer::timg::TimerGroup;
|
||||||
use esp_storage::FlashStorage;
|
use esp_storage::FlashStorage;
|
||||||
use esp_wifi::{init, EspWifiController};
|
use esp_wifi::{init, EspWifiController};
|
||||||
use littlefs2::fs::{Allocation, Filesystem as lfs2Filesystem};
|
use littlefs2::fs::{Allocation, Filesystem as lfs2Filesystem};
|
||||||
use littlefs2::object_safe::DynStorage;
|
use littlefs2::object_safe::DynStorage;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
use crate::log::{LogArray, LOG_ACCESS};
|
||||||
|
|
||||||
|
pub static TIME_ACCESS: OnceLock<Rtc> = OnceLock::new();
|
||||||
|
|
||||||
//Only support for 8 right now!
|
//Only support for 8 right now!
|
||||||
pub const PLANT_COUNT: usize = 8;
|
pub const PLANT_COUNT: usize = 8;
|
||||||
@ -181,6 +189,13 @@ impl PlantHal {
|
|||||||
|
|
||||||
esp_alloc::heap_allocator!(size: 64 * 1024);
|
esp_alloc::heap_allocator!(size: 64 * 1024);
|
||||||
esp_alloc::heap_allocator!(#[link_section = ".dram2_uninit"] size: 64000);
|
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 systimer = SystemTimer::new(peripherals.SYSTIMER);
|
||||||
|
|
||||||
let boot_button = Input::new(
|
let boot_button = Input::new(
|
||||||
@ -335,36 +350,78 @@ impl PlantHal {
|
|||||||
//init,reset rtc memory depending on cause
|
//init,reset rtc memory depending on cause
|
||||||
let mut init_rtc_store: bool = false;
|
let mut init_rtc_store: bool = false;
|
||||||
let mut to_config_mode: bool = false;
|
let mut to_config_mode: bool = false;
|
||||||
let reasons = "";
|
let reasons = match reset_reason() {
|
||||||
// let reasons = ResetReason::get();
|
None => {
|
||||||
// match reasons {
|
"unknown"
|
||||||
// ResetReason::Software => {}
|
}
|
||||||
// ResetReason::ExternalPin => {}
|
Some(reason) => {
|
||||||
// ResetReason::Watchdog => {
|
match reason {
|
||||||
// init_rtc_store = true;
|
SocResetReason::ChipPowerOn => {
|
||||||
// }
|
"power on"
|
||||||
// ResetReason::Sdio => init_rtc_store = true,
|
}
|
||||||
// ResetReason::Panic => init_rtc_store = true,
|
SocResetReason::CoreSw => {
|
||||||
// ResetReason::InterruptWatchdog => init_rtc_store = true,
|
"software reset"
|
||||||
// ResetReason::PowerOn => init_rtc_store = true,
|
}
|
||||||
// ResetReason::Unknown => init_rtc_store = true,
|
SocResetReason::CoreDeepSleep => {
|
||||||
// ResetReason::Brownout => init_rtc_store = true,
|
"deep sleep"
|
||||||
// ResetReason::TaskWatchdog => init_rtc_store = true,
|
}
|
||||||
// ResetReason::DeepSleep => {}
|
SocResetReason::CoreSDIO => {
|
||||||
// ResetReason::USBPeripheral => {
|
"sdio reset"
|
||||||
// init_rtc_store = true;
|
}
|
||||||
// to_config_mode = true;
|
SocResetReason::CoreMwdt0 => {
|
||||||
// }
|
"Watchdog Main"
|
||||||
// ResetReason::JTAG => init_rtc_store = true,
|
}
|
||||||
// };
|
SocResetReason::CoreMwdt1 => {
|
||||||
log(
|
"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,
|
LogMessage::ResetReason,
|
||||||
init_rtc_store as u32,
|
init_rtc_store as u32,
|
||||||
to_config_mode as u32,
|
to_config_mode as u32,
|
||||||
"",
|
"",
|
||||||
&format!("{reasons:?}"),
|
&format!("{reasons:?}"),
|
||||||
)
|
).await;
|
||||||
.await;
|
|
||||||
|
|
||||||
esp.init_rtc_deepsleep_memory(init_rtc_store, to_config_mode)
|
esp.init_rtc_deepsleep_memory(init_rtc_store, to_config_mode)
|
||||||
.await;
|
.await;
|
||||||
@ -430,32 +487,32 @@ impl PlantHal {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let board_hal: Box<dyn BoardInteraction + Send> = match config.hardware.board {
|
let board_hal: Box<dyn BoardInteraction + Send> = //match config.hardware.board {
|
||||||
BoardVersion::INITIAL => {
|
//BoardVersion::INITIAL => {
|
||||||
initial_hal::create_initial_board(free_pins, config, esp)?
|
initial_hal::create_initial_board(free_pins, config, esp)?
|
||||||
}
|
;
|
||||||
|
//}
|
||||||
// BoardVersion::V3 => {
|
// BoardVersion::V3 => {
|
||||||
// v3_hal::create_v3(free_pins, esp, config, battery_interaction, rtc_module)?
|
// v3_hal::create_v3(free_pins, esp, config, battery_interaction, rtc_module)?
|
||||||
// }
|
// }
|
||||||
// BoardVersion::V4 => {
|
//BoardVersion::V4 => {
|
||||||
// v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)?
|
// v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)?
|
||||||
// }
|
//}
|
||||||
_ => {
|
//_ => {
|
||||||
todo!()
|
// todo!()
|
||||||
}
|
//}
|
||||||
};
|
//};
|
||||||
|
|
||||||
HAL { board_hal }
|
HAL { board_hal }
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log(
|
LOG_ACCESS.lock().await.log(
|
||||||
LogMessage::ConfigModeMissingConfig,
|
LogMessage::ConfigModeMissingConfig,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
&err.to_string(),
|
&err.to_string(),
|
||||||
)
|
).await;
|
||||||
.await;
|
|
||||||
HAL {
|
HAL {
|
||||||
board_hal: initial_hal::create_initial_board(
|
board_hal: initial_hal::create_initial_board(
|
||||||
free_pins,
|
free_pins,
|
||||||
@ -469,3 +526,12 @@ impl PlantHal {
|
|||||||
Ok(Mutex::new(hal))
|
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 crate::vec;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use bytemuck::{AnyBitPattern, Contiguous, Pod, Zeroable};
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::lazy_lock::LazyLock;
|
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_time::Instant;
|
use embassy_time::Instant;
|
||||||
use esp_println::println;
|
use esp_hal::Persistable;
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use strum_macros::IntoStaticStr;
|
use strum_macros::IntoStaticStr;
|
||||||
|
|
||||||
use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
|
|
||||||
use unit_enum::UnitEnum;
|
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_SHORT_LENGTH: usize = 8;
|
||||||
const TXT_LONG_LENGTH: usize = 32;
|
const TXT_LONG_LENGTH: usize = 32;
|
||||||
|
|
||||||
const BUFFER_SIZE: usize = 220;
|
|
||||||
|
|
||||||
#[link_section = ".rtc.data"]
|
#[derive(Debug, Clone, Copy, AnyBitPattern)]
|
||||||
static mut BUFFER: ConstGenericRingBuffer<LogEntry, BUFFER_SIZE> =
|
#[repr(C)]
|
||||||
ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
pub struct LogArray{
|
||||||
#[allow(static_mut_refs)]
|
buffer: [LogEntryInner; (u8::MAX_VALUE as usize) +1],
|
||||||
static BUFFER_ACCESS: LazyLock<
|
head: u8
|
||||||
Mutex<CriticalSectionRawMutex, &mut ConstGenericRingBuffer<LogEntry, BUFFER_SIZE>>,
|
}
|
||||||
> = LazyLock::new(|| unsafe { Mutex::new(&mut BUFFER) });
|
|
||||||
|
|
||||||
#[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 struct LogEntry {
|
||||||
pub timestamp: u64,
|
pub timestamp: u64,
|
||||||
pub message_id: u16,
|
pub message_id: u16,
|
||||||
pub a: u32,
|
pub a: u32,
|
||||||
pub b: u32,
|
pub b: u32,
|
||||||
pub txt_short: heapless::String<TXT_SHORT_LENGTH>,
|
pub txt_short: alloc::string::String,
|
||||||
pub txt_long: heapless::String<TXT_LONG_LENGTH>,
|
pub txt_long: alloc::string::String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn init() {
|
impl From<LogEntryInner> for LogEntry {
|
||||||
unsafe {
|
fn from(value: LogEntryInner) -> Self {
|
||||||
BUFFER = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
LogEntry{
|
||||||
};
|
timestamp: value.timestamp,
|
||||||
let mut access = BUFFER_ACCESS.get().lock().await;
|
message_id: value.message_id,
|
||||||
access.drain().for_each(|_| {});
|
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>) {
|
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
while target.len() < LIMIT {
|
||||||
|
target.push(' ').unwrap();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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)]
|
#[derive(IntoStaticStr, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone, UnitEnum)]
|
||||||
pub enum LogMessage {
|
pub enum LogMessage {
|
||||||
|
#[strum(
|
||||||
|
serialize = ""
|
||||||
|
)]
|
||||||
|
Empty,
|
||||||
#[strum(
|
#[strum(
|
||||||
serialize = "Reset due to ${txt_long} requires rtc clear ${number_a} and force config mode ${number_b}"
|
serialize = "Reset due to ${txt_long} requires rtc clear ${number_a} and force config mode ${number_b}"
|
||||||
)]
|
)]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
|
#![feature(string_from_utf8_lossy_owned)]
|
||||||
#![deny(
|
#![deny(
|
||||||
clippy::mem_forget,
|
clippy::mem_forget,
|
||||||
reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
|
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_hal::system::software_reset;
|
||||||
use esp_println::{logger, println};
|
use esp_println::{logger, println};
|
||||||
use hal::battery::BatteryState;
|
use hal::battery::BatteryState;
|
||||||
use log::{log, LogMessage};
|
use log::{ LogMessage};
|
||||||
use plant_state::PlantState;
|
use plant_state::PlantState;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::hal::esp_time;
|
||||||
|
use crate::log::LOG_ACCESS;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn custom_halt() -> ! {
|
extern "C" fn custom_halt() -> ! {
|
||||||
@ -180,6 +183,7 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
|
|||||||
let _ota_state_string = "unknown";
|
let _ota_state_string = "unknown";
|
||||||
|
|
||||||
board.board_hal.general_fault(false).await;
|
board.board_hal.general_fault(false).await;
|
||||||
|
let time = esp_time().await;
|
||||||
let cur = board
|
let cur = board
|
||||||
.board_hal
|
.board_hal
|
||||||
.get_rtc_module()
|
.get_rtc_module()
|
||||||
@ -188,19 +192,19 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
|
|||||||
.or_else(|err| {
|
.or_else(|err| {
|
||||||
info!("rtc module error: {:?}", err);
|
info!("rtc module error: {:?}", err);
|
||||||
board.board_hal.general_fault(true);
|
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)
|
//check if we know the time current > 2020 (plausibility checks, this code is newer than 2020)
|
||||||
if cur.year() < 2020 {
|
if cur.year() < 2020 {
|
||||||
to_config = true;
|
to_config = true;
|
||||||
log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "").await;
|
LOG_ACCESS.lock().await.log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "").await;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("cur is {}", cur);
|
info!("cur is {}", cur);
|
||||||
update_charge_indicator(&mut board).await;
|
update_charge_indicator(&mut board).await;
|
||||||
println!("faul led3");
|
println!("faul led3");
|
||||||
if board.board_hal.get_esp().get_restart_to_conf() {
|
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 {
|
for _i in 0..2 {
|
||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
Timer::after_millis(100).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);
|
board.board_hal.get_esp().set_restart_to_conf(false);
|
||||||
} else if board.board_hal.get_esp().mode_override_pressed() {
|
} else if board.board_hal.get_esp().mode_override_pressed() {
|
||||||
board.board_hal.general_fault(true).await;
|
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 {
|
for _i in 0..5 {
|
||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
Timer::after_millis(100).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;
|
let _ = publish_mppt_state(&mut board).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(
|
LOG_ACCESS.lock().await.log(
|
||||||
LogMessage::StartupInfo,
|
LogMessage::StartupInfo,
|
||||||
matches!(network_mode, NetworkMode::WIFI { .. }) as u32,
|
matches!(network_mode, NetworkMode::WIFI { .. }) as u32,
|
||||||
matches!(
|
matches!(
|
||||||
@ -307,8 +311,8 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> {
|
|||||||
.to_string()
|
.to_string()
|
||||||
.as_str(),
|
.as_str(),
|
||||||
"",
|
"",
|
||||||
)
|
).await
|
||||||
.await;
|
;
|
||||||
|
|
||||||
if to_config {
|
if to_config {
|
||||||
//check if client or ap mode and init Wi-Fi
|
//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;
|
let board = BOARD_ACCESS.get().await.lock().await;
|
||||||
wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await;
|
wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await;
|
||||||
} else {
|
} else {
|
||||||
log(LogMessage::NormalRun, 0, 0, "", "").await;
|
LOG_ACCESS.lock().await.log(LogMessage::NormalRun, 0, 0, "", "").await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _dry_run = false;
|
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;
|
let high_current = current_ma > plant_config.max_pump_current_ma;
|
||||||
if high_current {
|
if high_current {
|
||||||
if first_error {
|
if first_error {
|
||||||
log(
|
LOG_ACCESS.lock().await.log(
|
||||||
LogMessage::PumpOverCurrent,
|
LogMessage::PumpOverCurrent,
|
||||||
plant_id as u32 + 1,
|
plant_id as u32 + 1,
|
||||||
current_ma as u32,
|
current_ma as u32,
|
||||||
plant_config.max_pump_current_ma.to_string().as_str(),
|
plant_config.max_pump_current_ma.to_string().as_str(),
|
||||||
step.to_string().as_str(),
|
step.to_string().as_str(),
|
||||||
)
|
).await
|
||||||
.await;
|
;
|
||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
board.board_hal.fault(plant_id, true).await?;
|
board.board_hal.fault(plant_id, true).await?;
|
||||||
if !plant_config.ignore_current_error {
|
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;
|
let low_current = current_ma < plant_config.min_pump_current_ma;
|
||||||
if low_current {
|
if low_current {
|
||||||
if first_error {
|
if first_error {
|
||||||
log(
|
LOG_ACCESS.lock().await.log(
|
||||||
LogMessage::PumpOpenLoopCurrent,
|
LogMessage::PumpOpenLoopCurrent,
|
||||||
plant_id as u32 + 1,
|
plant_id as u32 + 1,
|
||||||
current_ma as u32,
|
current_ma as u32,
|
||||||
plant_config.min_pump_current_ma.to_string().as_str(),
|
plant_config.min_pump_current_ma.to_string().as_str(),
|
||||||
step.to_string().as_str(),
|
step.to_string().as_str(),
|
||||||
)
|
).await
|
||||||
.await;
|
;
|
||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
board.board_hal.fault(plant_id, true).await?;
|
board.board_hal.fault(plant_id, true).await?;
|
||||||
if !plant_config.ignore_current_error {
|
if !plant_config.ignore_current_error {
|
||||||
@ -699,14 +703,14 @@ pub async fn do_secure_pump(
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
if !plant_config.ignore_current_error {
|
if !plant_config.ignore_current_error {
|
||||||
info!("Error getting pump current: {}", err);
|
info!("Error getting pump current: {}", err);
|
||||||
log(
|
LOG_ACCESS.lock().await.log(
|
||||||
LogMessage::PumpMissingSensorCurrent,
|
LogMessage::PumpMissingSensorCurrent,
|
||||||
plant_id as u32,
|
plant_id as u32,
|
||||||
0,
|
0,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
)
|
).await
|
||||||
.await;
|
;
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@ -1058,7 +1062,7 @@ async fn wait_infinity(
|
|||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.board_hal
|
.board_hal
|
||||||
.deep_sleep(1);
|
.deep_sleep(0).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,29 +3,30 @@
|
|||||||
use crate::config::PlantControllerConfig;
|
use crate::config::PlantControllerConfig;
|
||||||
use crate::{get_version, log::LogMessage, BOARD_ACCESS};
|
use crate::{get_version, log::LogMessage, BOARD_ACCESS};
|
||||||
use alloc::borrow::ToOwned;
|
use alloc::borrow::ToOwned;
|
||||||
use alloc::fmt::format;
|
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
use alloc::string::{String, ToString};
|
use alloc::string::{String, ToString};
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use anyhow::bail;
|
use anyhow::{bail};
|
||||||
use core::fmt::{Debug, Display};
|
use core::fmt::{Debug, Display};
|
||||||
use core::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use core::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
use core::result::Result::Ok;
|
use core::result::Result::Ok;
|
||||||
use core::str::from_utf8;
|
use core::str::from_utf8;
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use chrono::DateTime;
|
||||||
use edge_http::io::server::{Connection, Handler, Server};
|
use edge_http::io::server::{Connection, Handler, Server};
|
||||||
use edge_http::io::Error;
|
use edge_http::io::Error;
|
||||||
use edge_http::Method;
|
use edge_http::Method;
|
||||||
use edge_nal::{TcpBind, TcpSplit};
|
use edge_nal::{TcpBind};
|
||||||
use edge_nal_embassy::{Tcp, TcpBuffers};
|
use edge_nal_embassy::{Tcp, TcpBuffers};
|
||||||
use embassy_net::Stack;
|
use embassy_net::Stack;
|
||||||
use embassy_time::Instant;
|
use embassy_time::Instant;
|
||||||
use embedded_io_async::{Read, Write};
|
use embedded_io_async::{Read, Write};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
use littlefs2_core::Path;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::hal::{esp_set_time, esp_time};
|
||||||
|
use crate::log::{LOG_ACCESS};
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
struct SSIDList {
|
struct SSIDList {
|
||||||
@ -72,25 +73,6 @@ pub struct NightLampCommand {
|
|||||||
active: bool,
|
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?;
|
conn.write_all(include_bytes!("bundle.js")).await?;
|
||||||
Some(200)
|
Some(200)
|
||||||
}
|
}
|
||||||
"/reboot" => {
|
"/log" => {
|
||||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
let buf = get_log(conn).await;
|
||||||
board.board_hal.get_esp().set_restart_to_conf(true);
|
|
||||||
self.reboot_now.store(true, Ordering::Relaxed);
|
|
||||||
Some(200)
|
Some(200)
|
||||||
}
|
},
|
||||||
&_ => {
|
&_ => {
|
||||||
let json = match path {
|
let json = match path {
|
||||||
"/version" => Some(get_version_web(conn).await),
|
"/version" => Some(get_version_web(conn).await),
|
||||||
@ -445,7 +425,6 @@ impl Handler for HttpHandler {
|
|||||||
"/get_config" => Some(get_config(conn).await),
|
"/get_config" => Some(get_config(conn).await),
|
||||||
"/files" => Some(list_files(conn).await),
|
"/files" => Some(list_files(conn).await),
|
||||||
"/log_localization" => Some(get_log_localization_config(conn).await),
|
"/log_localization" => Some(get_log_localization_config(conn).await),
|
||||||
"/log" => Some(get_log(conn).await),
|
|
||||||
"/wifiscan" => Some(wifi_scan(conn).await),
|
"/wifiscan" => Some(wifi_scan(conn).await),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
@ -459,6 +438,13 @@ impl Handler for HttpHandler {
|
|||||||
let json = match path {
|
let json = match path {
|
||||||
"/wifiscan" => Some(wifi_scan(conn).await),
|
"/wifiscan" => Some(wifi_scan(conn).await),
|
||||||
"/set_config" => Some(set_config(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,
|
_ => None,
|
||||||
};
|
};
|
||||||
match json {
|
match json {
|
||||||
@ -568,6 +554,20 @@ impl Handler for HttpHandler {
|
|||||||
// })
|
// })
|
||||||
// .unwrap();
|
// .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>(
|
async fn set_config<T, const N: usize>(
|
||||||
request: &mut Connection<'_, T, N>,
|
request: &mut Connection<'_, T, N>,
|
||||||
) -> Result<Option<String>, anyhow::Error>
|
) -> 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>(
|
async fn get_log<T, const N: usize>(
|
||||||
_request: &mut Connection<'_, T, N>,
|
conn: &mut Connection<'_, T, N>,
|
||||||
) -> Result<Option<String>, anyhow::Error> {
|
) -> anyhow::Result<()>
|
||||||
let output = crate::log::get_log().await;
|
where
|
||||||
anyhow::Ok(Some(serde_json::to_string(&output)?))
|
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>(
|
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> {
|
) -> Result<Option<String>, anyhow::Error> {
|
||||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||||
//TODO do not fail if rtc module is missing
|
//TODO do not fail if rtc module is missing
|
||||||
let native = board.board_hal.get_esp().time().to_rfc3339();
|
let native = esp_time().await.to_rfc3339();
|
||||||
let rtc = board
|
let rtc = "todo";
|
||||||
.board_hal
|
// board
|
||||||
.get_rtc_module()
|
// .board_hal
|
||||||
.get_rtc_time()
|
// .get_rtc_module()
|
||||||
.await?
|
// .get_rtc_time()
|
||||||
.to_rfc3339();
|
// .await?
|
||||||
|
// .to_rfc3339();
|
||||||
|
|
||||||
let data = LoadData {
|
let data = LoadData {
|
||||||
rtc: rtc.as_str(),
|
rtc,
|
||||||
native: native.as_str(),
|
native: native.as_str(),
|
||||||
};
|
};
|
||||||
let json = serde_json::to_string(&data)?;
|
let json = serde_json::to_string(&data)?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user