refactor: consolidate logging and time handling, remove TIME_ACCESS and LOG_ACCESS
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
use crate::bail;
|
use crate::bail;
|
||||||
use crate::config::{NetworkConfig, PlantControllerConfig};
|
use crate::config::{NetworkConfig, PlantControllerConfig};
|
||||||
use crate::hal::savegame_manager::SavegameManager;
|
use crate::hal::savegame_manager::SavegameManager;
|
||||||
use crate::hal::{PLANT_COUNT, TIME_ACCESS};
|
use crate::hal::PLANT_COUNT;
|
||||||
use crate::log::{LogMessage, LOG_ACCESS};
|
use crate::log::{log, LogMessage};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
use crate::fat_error::{ContextExt, FatError, FatResult};
|
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||||
@@ -16,7 +16,7 @@ use embassy_executor::Spawner;
|
|||||||
use embassy_net::udp::UdpSocket;
|
use embassy_net::udp::UdpSocket;
|
||||||
use embassy_net::{DhcpConfig, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
use embassy_net::{DhcpConfig, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::mutex::{Mutex, MutexGuard};
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::once_lock::OnceLock;
|
use embassy_sync::once_lock::OnceLock;
|
||||||
use embassy_time::{Duration, Timer, WithTimeout};
|
use embassy_time::{Duration, Timer, WithTimeout};
|
||||||
use embedded_storage::nor_flash::{check_erase, NorFlash, ReadNorFlash, RmwNorFlashStorage};
|
use embedded_storage::nor_flash::{check_erase, NorFlash, ReadNorFlash, RmwNorFlashStorage};
|
||||||
@@ -112,6 +112,8 @@ pub struct Esp<'a> {
|
|||||||
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
|
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
|
||||||
pub uart0: Uart<'a, Blocking>,
|
pub uart0: Uart<'a, Blocking>,
|
||||||
|
|
||||||
|
pub rtc: Rtc<'a>,
|
||||||
|
|
||||||
pub ota: Ota<'static, RmwNorFlashStorage<'static, &'static mut MutexFlashStorage>>,
|
pub ota: Ota<'static, RmwNorFlashStorage<'static, &'static mut MutexFlashStorage>>,
|
||||||
pub ota_target: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
pub ota_target: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
||||||
pub current: AppPartitionSubType,
|
pub current: AppPartitionSubType,
|
||||||
@@ -137,6 +139,14 @@ macro_rules! mk_static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Esp<'_> {
|
impl Esp<'_> {
|
||||||
|
pub fn get_time(&self) -> DateTime<Utc> {
|
||||||
|
DateTime::from_timestamp_micros(self.rtc.current_time_us() as i64).unwrap_or(DateTime::UNIX_EPOCH)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_time(&mut self, time: DateTime<Utc>) {
|
||||||
|
self.rtc.set_current_time_us(time.timestamp_micros() as u64);
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn read_serial_line(&mut self) -> FatResult<Option<alloc::string::String>> {
|
pub(crate) async fn read_serial_line(&mut self) -> FatResult<Option<alloc::string::String>> {
|
||||||
let mut buf = [0u8; 1];
|
let mut buf = [0u8; 1];
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
@@ -442,70 +452,65 @@ impl Esp<'_> {
|
|||||||
spawner.spawn(net_task(runner)).ok();
|
spawner.spawn(net_task(runner)).ok();
|
||||||
self.controller.lock().await.start_async().await?;
|
self.controller.lock().await.start_async().await?;
|
||||||
|
|
||||||
let timeout = {
|
let res = async {
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
loop {
|
||||||
guard.current_time_us()
|
let state = esp_radio::wifi::sta_state();
|
||||||
} + max_wait as u64 * 1000;
|
if state == WifiStaState::Started {
|
||||||
loop {
|
self.controller.lock().await.connect()?;
|
||||||
let state = esp_radio::wifi::sta_state();
|
break;
|
||||||
if state == WifiStaState::Started {
|
}
|
||||||
self.controller.lock().await.connect()?;
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if {
|
Ok::<(), FatError>(())
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
|
||||||
guard.current_time_us()
|
|
||||||
} > timeout
|
|
||||||
{
|
|
||||||
bail!("Timeout waiting for wifi sta ready")
|
|
||||||
}
|
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
|
||||||
}
|
}
|
||||||
let timeout = {
|
.with_timeout(Duration::from_millis(max_wait as u64 * 1000))
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
.await;
|
||||||
guard.current_time_us()
|
|
||||||
} + max_wait as u64 * 1000;
|
if res.is_err() {
|
||||||
loop {
|
bail!("Timeout waiting for wifi sta ready")
|
||||||
let state = esp_radio::wifi::sta_state();
|
|
||||||
if state == WifiStaState::Connected {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if {
|
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
|
||||||
guard.current_time_us()
|
|
||||||
} > timeout
|
|
||||||
{
|
|
||||||
bail!("Timeout waiting for wifi sta connected")
|
|
||||||
}
|
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
|
||||||
}
|
}
|
||||||
let timeout = {
|
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
let res = async {
|
||||||
guard.current_time_us()
|
loop {
|
||||||
} + max_wait as u64 * 1000;
|
let state = esp_radio::wifi::sta_state();
|
||||||
while !stack.is_link_up() {
|
if state == WifiStaState::Connected {
|
||||||
if {
|
break;
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
}
|
||||||
guard.current_time_us()
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
} > timeout
|
|
||||||
{
|
|
||||||
bail!("Timeout waiting for wifi link up")
|
|
||||||
}
|
}
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
Ok::<(), FatError>(())
|
||||||
}
|
}
|
||||||
let timeout = {
|
.with_timeout(Duration::from_millis(max_wait as u64 * 1000))
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
.await;
|
||||||
guard.current_time_us()
|
|
||||||
} + max_wait as u64 * 1000;
|
if res.is_err() {
|
||||||
while !stack.is_config_up() {
|
bail!("Timeout waiting for wifi sta connected")
|
||||||
if {
|
}
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
|
||||||
guard.current_time_us()
|
let res = async {
|
||||||
} > timeout
|
while !stack.is_link_up() {
|
||||||
{
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
bail!("Timeout waiting for wifi config up")
|
|
||||||
}
|
}
|
||||||
Timer::after(Duration::from_millis(100)).await
|
Ok::<(), FatError>(())
|
||||||
|
}
|
||||||
|
.with_timeout(Duration::from_millis(max_wait as u64 * 1000))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if res.is_err() {
|
||||||
|
bail!("Timeout waiting for wifi link up")
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = async {
|
||||||
|
while !stack.is_config_up() {
|
||||||
|
Timer::after(Duration::from_millis(100)).await
|
||||||
|
}
|
||||||
|
Ok::<(), FatError>(())
|
||||||
|
}
|
||||||
|
.with_timeout(Duration::from_millis(max_wait as u64 * 1000))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if res.is_err() {
|
||||||
|
bail!("Timeout waiting for wifi config up")
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Connected WIFI, dhcp: {:?}", stack.config_v4());
|
info!("Connected WIFI, dhcp: {:?}", stack.config_v4());
|
||||||
@@ -515,7 +520,6 @@ impl Esp<'_> {
|
|||||||
pub fn deep_sleep(
|
pub fn deep_sleep(
|
||||||
&mut self,
|
&mut self,
|
||||||
duration_in_ms: u64,
|
duration_in_ms: u64,
|
||||||
mut rtc: MutexGuard<CriticalSectionRawMutex, Rtc>,
|
|
||||||
) -> ! {
|
) -> ! {
|
||||||
// Mark the current OTA image as valid if we reached here while in pending verify.
|
// Mark the current OTA image as valid if we reached here while in pending verify.
|
||||||
if let Ok(cur) = self.ota.current_ota_state() {
|
if let Ok(cur) = self.ota.current_ota_state() {
|
||||||
@@ -536,7 +540,7 @@ impl Esp<'_> {
|
|||||||
let mut wake_pins: [(&mut dyn RtcPinWithResistors, WakeupLevel); 1] =
|
let mut wake_pins: [(&mut dyn RtcPinWithResistors, WakeupLevel); 1] =
|
||||||
[(&mut self.wake_gpio1, WakeupLevel::Low)];
|
[(&mut self.wake_gpio1, WakeupLevel::Low)];
|
||||||
let ext1 = esp_hal::rtc_cntl::sleep::Ext1WakeupSource::new(&mut wake_pins);
|
let ext1 = esp_hal::rtc_cntl::sleep::Ext1WakeupSource::new(&mut wake_pins);
|
||||||
rtc.sleep_deep(&[&timer, &ext1]);
|
self.rtc.sleep_deep(&[&timer, &ext1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,28 +607,15 @@ impl Esp<'_> {
|
|||||||
if to_config_mode {
|
if to_config_mode {
|
||||||
RESTART_TO_CONF = 1;
|
RESTART_TO_CONF = 1;
|
||||||
}
|
}
|
||||||
LOG_ACCESS
|
log(LogMessage::RestartToConfig, RESTART_TO_CONF as u32, 0, "", "").await;
|
||||||
.lock()
|
log(
|
||||||
.await
|
LogMessage::LowVoltage,
|
||||||
.log(
|
LOW_VOLTAGE_DETECTED as u32,
|
||||||
LogMessage::RestartToConfig,
|
0,
|
||||||
RESTART_TO_CONF as u32,
|
"",
|
||||||
0,
|
"",
|
||||||
"",
|
)
|
||||||
"",
|
.await;
|
||||||
)
|
|
||||||
.await;
|
|
||||||
LOG_ACCESS
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(
|
|
||||||
LogMessage::LowVoltage,
|
|
||||||
LOW_VOLTAGE_DETECTED as u32,
|
|
||||||
0,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
// is executed before main, no other code will alter these values during printing
|
// is executed before main, no other code will alter these values during printing
|
||||||
#[allow(static_mut_refs)]
|
#[allow(static_mut_refs)]
|
||||||
for (i, time) in LAST_WATERING_TIMESTAMP.iter().enumerate() {
|
for (i, time) in LAST_WATERING_TIMESTAMP.iter().enumerate() {
|
||||||
@@ -703,29 +694,22 @@ impl Esp<'_> {
|
|||||||
))?;
|
))?;
|
||||||
spawner.spawn(mqtt_runner(task))?;
|
spawner.spawn(mqtt_runner(task))?;
|
||||||
|
|
||||||
LOG_ACCESS
|
log(LogMessage::StayAlive, 0, 0, "", &stay_alive_topic).await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::StayAlive, 0, 0, "", &stay_alive_topic)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
LOG_ACCESS
|
log(LogMessage::MqttInfo, 0, 0, "", mqtt_url).await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::MqttInfo, 0, 0, "", mqtt_url)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let mqtt_timeout = 15000;
|
let mqtt_timeout = 15000;
|
||||||
let timeout = {
|
let res = async {
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
while !MQTT_CONNECTED_EVENT_RECEIVED.load(Ordering::Relaxed) {
|
||||||
guard.current_time_us()
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
} + mqtt_timeout as u64 * 1000;
|
|
||||||
while !MQTT_CONNECTED_EVENT_RECEIVED.load(Ordering::Relaxed) {
|
|
||||||
let cur = TIME_ACCESS.get().await.lock().await.current_time_us();
|
|
||||||
if cur > timeout {
|
|
||||||
bail!("Timeout waiting MQTT connect event")
|
|
||||||
}
|
}
|
||||||
Timer::after(Duration::from_millis(100)).await;
|
Ok::<(), FatError>(())
|
||||||
|
}
|
||||||
|
.with_timeout(Duration::from_millis(mqtt_timeout as u64))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if res.is_err() {
|
||||||
|
bail!("Timeout waiting MQTT connect event")
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = Topic::General(round_trip_topic.clone())
|
let _ = Topic::General(round_trip_topic.clone())
|
||||||
@@ -733,18 +717,19 @@ impl Esp<'_> {
|
|||||||
.publish()
|
.publish()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let timeout = {
|
let res = async {
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
while !MQTT_ROUND_TRIP_RECEIVED.load(Ordering::Relaxed) {
|
||||||
guard.current_time_us()
|
Timer::after(Duration::from_millis(100)).await;
|
||||||
} + mqtt_timeout as u64 * 1000;
|
|
||||||
while !MQTT_ROUND_TRIP_RECEIVED.load(Ordering::Relaxed) {
|
|
||||||
let cur = TIME_ACCESS.get().await.lock().await.current_time_us();
|
|
||||||
if cur > timeout {
|
|
||||||
//ensure we do not further try to publish
|
|
||||||
MQTT_CONNECTED_EVENT_RECEIVED.store(false, Ordering::Relaxed);
|
|
||||||
bail!("Timeout waiting MQTT roundtrip")
|
|
||||||
}
|
}
|
||||||
Timer::after(Duration::from_millis(100)).await;
|
Ok::<(), FatError>(())
|
||||||
|
}
|
||||||
|
.with_timeout(Duration::from_millis(mqtt_timeout as u64))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if res.is_err() {
|
||||||
|
//ensure we do not further try to publish
|
||||||
|
MQTT_CONNECTED_EVENT_RECEIVED.store(false, Ordering::Relaxed);
|
||||||
|
bail!("Timeout waiting MQTT roundtrip")
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -851,18 +836,10 @@ async fn mqtt_incoming_task(
|
|||||||
true => 1,
|
true => 1,
|
||||||
false => 0,
|
false => 0,
|
||||||
};
|
};
|
||||||
LOG_ACCESS
|
log(LogMessage::MqttStayAliveRec, a, 0, "", "").await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::MqttStayAliveRec, a, 0, "", "")
|
|
||||||
.await;
|
|
||||||
MQTT_STAY_ALIVE.store(value, Ordering::Relaxed);
|
MQTT_STAY_ALIVE.store(value, Ordering::Relaxed);
|
||||||
} else {
|
} else {
|
||||||
LOG_ACCESS
|
log(LogMessage::UnknownTopic, 0, 0, "", &topic).await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::UnknownTopic, 0, 0, "", &topic)
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ use crate::{
|
|||||||
battery::{BatteryInteraction, NoBatteryMonitor},
|
battery::{BatteryInteraction, NoBatteryMonitor},
|
||||||
esp::Esp,
|
esp::Esp,
|
||||||
},
|
},
|
||||||
|
log::log,
|
||||||
log::LogMessage,
|
log::LogMessage,
|
||||||
BOARD_ACCESS,
|
|
||||||
};
|
};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
@@ -77,7 +77,6 @@ use crate::fat_error::{ContextExt, FatError, FatResult};
|
|||||||
use crate::hal::battery::WCHI2CSlave;
|
use crate::hal::battery::WCHI2CSlave;
|
||||||
use crate::hal::savegame_manager::SavegameManager;
|
use crate::hal::savegame_manager::SavegameManager;
|
||||||
use crate::hal::water::TankSensor;
|
use crate::hal::water::TankSensor;
|
||||||
use crate::log::LOG_ACCESS;
|
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::once_lock::OnceLock;
|
use embassy_sync::once_lock::OnceLock;
|
||||||
use embedded_storage::nor_flash::RmwNorFlashStorage;
|
use embedded_storage::nor_flash::RmwNorFlashStorage;
|
||||||
@@ -104,8 +103,6 @@ use portable_atomic::AtomicBool;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use shared_flash::MutexFlashStorage;
|
use shared_flash::MutexFlashStorage;
|
||||||
|
|
||||||
pub static TIME_ACCESS: OnceLock<Mutex<CriticalSectionRawMutex, 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;
|
||||||
|
|
||||||
@@ -145,6 +142,8 @@ pub trait BoardInteraction<'a> {
|
|||||||
fn get_config(&mut self) -> &PlantControllerConfig;
|
fn get_config(&mut self) -> &PlantControllerConfig;
|
||||||
fn get_battery_monitor(&mut self) -> &mut Box<dyn BatteryInteraction + Send>;
|
fn get_battery_monitor(&mut self) -> &mut Box<dyn BatteryInteraction + Send>;
|
||||||
fn get_rtc_module(&mut self) -> &mut Box<dyn RTCModuleInteraction + Send>;
|
fn get_rtc_module(&mut self) -> &mut Box<dyn RTCModuleInteraction + Send>;
|
||||||
|
async fn get_time(&mut self) -> DateTime<Utc>;
|
||||||
|
async fn set_time(&mut self, time: &DateTime<FixedOffset>) -> FatResult<()>;
|
||||||
async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError>;
|
async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError>;
|
||||||
async fn deep_sleep(&mut self, duration_in_ms: u64) -> !;
|
async fn deep_sleep(&mut self, duration_in_ms: u64) -> !;
|
||||||
|
|
||||||
@@ -246,12 +245,7 @@ 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);
|
let rtc_peripheral: Rtc = Rtc::new(peripherals.LPWR);
|
||||||
TIME_ACCESS
|
|
||||||
.init(Mutex::new(rtc))
|
|
||||||
.map_err(|_| FatError::String {
|
|
||||||
error: "Init error rct".to_string(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||||
let sw_int = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
let sw_int = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||||
@@ -409,6 +403,7 @@ impl PlantHal {
|
|||||||
slot0_state: state_0,
|
slot0_state: state_0,
|
||||||
slot1_state: state_1,
|
slot1_state: state_1,
|
||||||
uart0,
|
uart0,
|
||||||
|
rtc: rtc_peripheral,
|
||||||
};
|
};
|
||||||
|
|
||||||
//init,reset rtc memory depending on cause
|
//init,reset rtc memory depending on cause
|
||||||
@@ -444,17 +439,14 @@ impl PlantHal {
|
|||||||
SocResetReason::Cpu0JtagCpu => "cpu0 jtag cpu",
|
SocResetReason::Cpu0JtagCpu => "cpu0 jtag cpu",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
LOG_ACCESS
|
log(
|
||||||
.lock()
|
LogMessage::ResetReason,
|
||||||
.await
|
init_rtc_store as u32,
|
||||||
.log(
|
to_config_mode as u32,
|
||||||
LogMessage::ResetReason,
|
"",
|
||||||
init_rtc_store as u32,
|
&format!("{reasons:?}"),
|
||||||
to_config_mode as u32,
|
)
|
||||||
"",
|
.await;
|
||||||
&format!("{reasons:?}"),
|
|
||||||
)
|
|
||||||
.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;
|
||||||
@@ -548,17 +540,14 @@ impl PlantHal {
|
|||||||
HAL { board_hal }
|
HAL { board_hal }
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
LOG_ACCESS
|
log(
|
||||||
.lock()
|
LogMessage::ConfigModeMissingConfig,
|
||||||
.await
|
0,
|
||||||
.log(
|
0,
|
||||||
LogMessage::ConfigModeMissingConfig,
|
"",
|
||||||
0,
|
&err.to_string(),
|
||||||
0,
|
)
|
||||||
"",
|
.await;
|
||||||
&err.to_string(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
HAL {
|
HAL {
|
||||||
board_hal: v4_hal::create_v4(
|
board_hal: v4_hal::create_v4(
|
||||||
free_pins,
|
free_pins,
|
||||||
@@ -641,27 +630,6 @@ pub fn next_partition(current: AppPartitionSubType) -> FatResult<AppPartitionSub
|
|||||||
Ok(next)
|
Ok(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn esp_time() -> DateTime<Utc> {
|
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
|
||||||
DateTime::from_timestamp_micros(guard.current_time_us() as i64).unwrap_or(DateTime::UNIX_EPOCH)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn esp_set_time(time: DateTime<FixedOffset>) -> FatResult<()> {
|
|
||||||
{
|
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
|
||||||
guard.set_current_time_us(time.timestamp_micros() as u64);
|
|
||||||
}
|
|
||||||
BOARD_ACCESS
|
|
||||||
.get()
|
|
||||||
.await
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.board_hal
|
|
||||||
.get_rtc_module()
|
|
||||||
.set_rtc_time(&time.to_utc())
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize)]
|
||||||
pub struct Moistures {
|
pub struct Moistures {
|
||||||
pub sensor_a_hz: [Option<f32>; PLANT_COUNT],
|
pub sensor_a_hz: [Option<f32>; PLANT_COUNT],
|
||||||
|
|||||||
@@ -7,15 +7,15 @@ use crate::hal::rtc::{BackupHeader, RTCModuleInteraction, EEPROM_PAGE, X25};
|
|||||||
use crate::hal::water::TankSensor;
|
use crate::hal::water::TankSensor;
|
||||||
use crate::hal::{
|
use crate::hal::{
|
||||||
BoardInteraction, Detection, FreePeripherals, Moistures, Sensor, I2C_DRIVER, PLANT_COUNT,
|
BoardInteraction, Detection, FreePeripherals, Moistures, Sensor, I2C_DRIVER, PLANT_COUNT,
|
||||||
TIME_ACCESS,
|
|
||||||
};
|
};
|
||||||
use crate::log::{LogMessage, LOG_ACCESS};
|
use crate::log::{log, LogMessage};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use bincode::config;
|
use bincode::config;
|
||||||
use canapi::id::{classify, plant_id, MessageKind, IDENTIFY_CMD_OFFSET};
|
use canapi::id::{classify, plant_id, MessageKind, IDENTIFY_CMD_OFFSET};
|
||||||
use canapi::SensorSlot;
|
use canapi::SensorSlot;
|
||||||
|
use chrono::{DateTime, FixedOffset, Utc};
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
@@ -300,6 +300,16 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
|||||||
&mut self.rtc_module
|
&mut self.rtc_module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_time(&mut self) -> DateTime<Utc> {
|
||||||
|
self.esp.get_time()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_time(&mut self, time: &DateTime<FixedOffset>) -> FatResult<()> {
|
||||||
|
self.rtc_module.set_rtc_time(&time.to_utc()).await?;
|
||||||
|
self.esp.set_time(time.to_utc());
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError> {
|
async fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError> {
|
||||||
self.charger.set_charge_indicator(charging)
|
self.charger.set_charge_indicator(charging)
|
||||||
}
|
}
|
||||||
@@ -307,8 +317,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
|||||||
async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
|
async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
|
||||||
self.awake.set_low();
|
self.awake.set_low();
|
||||||
self.charger.power_save();
|
self.charger.power_save();
|
||||||
let rtc = TIME_ACCESS.get().await.lock().await;
|
self.esp.deep_sleep(duration_in_ms);
|
||||||
self.esp.deep_sleep(duration_in_ms, rtc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_day(&self) -> bool {
|
fn is_day(&self) -> bool {
|
||||||
@@ -507,10 +516,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
|||||||
for plant in 0..PLANT_COUNT {
|
for plant in 0..PLANT_COUNT {
|
||||||
let a = moisture.sensor_a_hz[plant].unwrap_or(0.0) as u32;
|
let a = moisture.sensor_a_hz[plant].unwrap_or(0.0) as u32;
|
||||||
let b = moisture.sensor_b_hz[plant].unwrap_or(0.0) as u32;
|
let b = moisture.sensor_b_hz[plant].unwrap_or(0.0) as u32;
|
||||||
LOG_ACCESS
|
log(LogMessage::TestSensor, a, b, &(plant + 1).to_string(), "")
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::TestSensor, a, b, &(plant + 1).to_string(), "")
|
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
Timer::after_millis(10).await;
|
Timer::after_millis(10).await;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use crate::hal::TIME_ACCESS;
|
use crate::BOARD_ACCESS;
|
||||||
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, Pod, Zeroable};
|
use bytemuck::{AnyBitPattern, Pod, Zeroable};
|
||||||
use deranged::RangedU8;
|
use deranged::RangedU8;
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
|
use embassy_sync::channel::Channel;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use esp_hal::Persistable;
|
use esp_hal::Persistable;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
@@ -32,6 +33,34 @@ static mut LOG_ARRAY: LogArray = LogArray {
|
|||||||
pub static LOG_ACCESS: Mutex<CriticalSectionRawMutex, &'static mut LogArray> =
|
pub static LOG_ACCESS: Mutex<CriticalSectionRawMutex, &'static mut LogArray> =
|
||||||
unsafe { Mutex::new(&mut LOG_ARRAY) };
|
unsafe { Mutex::new(&mut LOG_ARRAY) };
|
||||||
|
|
||||||
|
pub struct LogRequest {
|
||||||
|
pub message_key: LogMessage,
|
||||||
|
pub number_a: u32,
|
||||||
|
pub number_b: u32,
|
||||||
|
pub txt_short: heapless::String<TXT_SHORT_LENGTH>,
|
||||||
|
pub txt_long: heapless::String<TXT_LONG_LENGTH>,
|
||||||
|
}
|
||||||
|
|
||||||
|
static LOG_CHANNEL: Channel<CriticalSectionRawMutex, LogRequest, 16> = Channel::new();
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
pub async fn log_task() {
|
||||||
|
loop {
|
||||||
|
let request = LOG_CHANNEL.receive().await;
|
||||||
|
LOG_ACCESS
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.log(
|
||||||
|
request.message_key,
|
||||||
|
request.number_a,
|
||||||
|
request.number_b,
|
||||||
|
request.txt_short.as_str(),
|
||||||
|
request.txt_long.as_str(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const TXT_SHORT_LENGTH: usize = 8;
|
const TXT_SHORT_LENGTH: usize = 8;
|
||||||
const TXT_LONG_LENGTH: usize = 32;
|
const TXT_LONG_LENGTH: usize = 32;
|
||||||
|
|
||||||
@@ -87,11 +116,21 @@ pub async fn log(
|
|||||||
txt_short: &str,
|
txt_short: &str,
|
||||||
txt_long: &str,
|
txt_long: &str,
|
||||||
) {
|
) {
|
||||||
LOG_ACCESS
|
let mut txt_short_stack: heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
|
||||||
.lock()
|
let mut txt_long_stack: heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
|
||||||
.await
|
|
||||||
.log(message_key, number_a, number_b, txt_short, txt_long)
|
limit_length(txt_short, &mut txt_short_stack);
|
||||||
.await
|
limit_length(txt_long, &mut txt_long_stack);
|
||||||
|
|
||||||
|
LOG_CHANNEL
|
||||||
|
.send(LogRequest {
|
||||||
|
message_key,
|
||||||
|
number_a,
|
||||||
|
number_b,
|
||||||
|
txt_short: txt_short_stack,
|
||||||
|
txt_long: txt_long_stack,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogArray {
|
impl LogArray {
|
||||||
@@ -122,15 +161,9 @@ impl LogArray {
|
|||||||
let mut head: RangedU8<0, MAX_LOG_ARRAY_INDEX> =
|
let mut head: RangedU8<0, MAX_LOG_ARRAY_INDEX> =
|
||||||
RangedU8::new(self.head).unwrap_or(RangedU8::new_saturating(0));
|
RangedU8::new(self.head).unwrap_or(RangedU8::new_saturating(0));
|
||||||
|
|
||||||
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 = {
|
let time = {
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
let mut guard = BOARD_ACCESS.get().await.lock().await;
|
||||||
guard.current_time_us()
|
guard.board_hal.get_esp().rtc.current_time_us()
|
||||||
} / 1000;
|
} / 1000;
|
||||||
|
|
||||||
let ordinal = message_key.ordinal() as u16;
|
let ordinal = message_key.ordinal() as u16;
|
||||||
@@ -148,12 +181,8 @@ impl LogArray {
|
|||||||
to_modify.message_id = ordinal;
|
to_modify.message_id = ordinal;
|
||||||
to_modify.a = number_a;
|
to_modify.a = number_a;
|
||||||
to_modify.b = number_b;
|
to_modify.b = number_b;
|
||||||
to_modify
|
to_modify.txt_short.clone_from_slice(txt_short.as_bytes());
|
||||||
.txt_short
|
to_modify.txt_long.clone_from_slice(txt_long.as_bytes());
|
||||||
.clone_from_slice(txt_short_stack.as_bytes());
|
|
||||||
to_modify
|
|
||||||
.txt_long
|
|
||||||
.clone_from_slice(txt_long_stack.as_bytes());
|
|
||||||
head = head.wrapping_add(1);
|
head = head.wrapping_add(1);
|
||||||
self.head = head.get();
|
self.head = head.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ use crate::config::{NetworkConfig, PlantConfig, PlantControllerConfig};
|
|||||||
use crate::fat_error::FatResult;
|
use crate::fat_error::FatResult;
|
||||||
use crate::hal::esp::MQTT_STAY_ALIVE;
|
use crate::hal::esp::MQTT_STAY_ALIVE;
|
||||||
use crate::hal::PROGRESS_ACTIVE;
|
use crate::hal::PROGRESS_ACTIVE;
|
||||||
use crate::hal::{esp_time, TIME_ACCESS};
|
use crate::log::log;
|
||||||
use crate::log::{log, LOG_ACCESS};
|
|
||||||
use crate::tank::{determine_tank_state, TankError, TankState, WATER_FROZEN_THRESH};
|
use crate::tank::{determine_tank_state, TankError, TankState, WATER_FROZEN_THRESH};
|
||||||
use crate::webserver::http_server;
|
use crate::webserver::http_server;
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -168,26 +167,21 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
let cur = match board.board_hal.get_rtc_module().get_rtc_time().await {
|
let cur = match board.board_hal.get_rtc_module().get_rtc_time().await {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
{
|
{
|
||||||
let guard = TIME_ACCESS.get().await.lock().await;
|
board.board_hal.get_esp().rtc.set_current_time_us(value.timestamp_micros() as u64);
|
||||||
guard.set_current_time_us(value.timestamp_micros() as u64);
|
|
||||||
}
|
}
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
info!("rtc module error: {err:?}");
|
info!("rtc module error: {err:?}");
|
||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
esp_time().await
|
board.board_hal.get_time().await
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//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_ACCESS
|
log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "").await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "")
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
info!("cur is {cur}");
|
info!("cur is {cur}");
|
||||||
match update_charge_indicator(&mut board).await {
|
match update_charge_indicator(&mut board).await {
|
||||||
@@ -200,11 +194,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if board.board_hal.get_esp().get_restart_to_conf() {
|
if board.board_hal.get_esp().get_restart_to_conf() {
|
||||||
LOG_ACCESS
|
log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "").await;
|
||||||
.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;
|
||||||
@@ -216,11 +206,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
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_ACCESS
|
log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "").await;
|
||||||
.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;
|
||||||
@@ -304,25 +290,22 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
let _ = publish_mppt_state(&mut board).await;
|
let _ = publish_mppt_state(&mut board).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ACCESS
|
log(
|
||||||
.lock()
|
LogMessage::StartupInfo,
|
||||||
.await
|
matches!(network_mode, NetworkMode::Wifi { .. }) as u32,
|
||||||
.log(
|
matches!(
|
||||||
LogMessage::StartupInfo,
|
network_mode,
|
||||||
matches!(network_mode, NetworkMode::Wifi { .. }) as u32,
|
NetworkMode::Wifi {
|
||||||
matches!(
|
sntp: SntpMode::Sync { .. },
|
||||||
network_mode,
|
..
|
||||||
NetworkMode::Wifi {
|
}
|
||||||
sntp: SntpMode::Sync { .. },
|
) as u32,
|
||||||
..
|
matches!(network_mode, NetworkMode::Wifi { mqtt: true, .. })
|
||||||
}
|
.to_string()
|
||||||
) as u32,
|
.as_str(),
|
||||||
matches!(network_mode, NetworkMode::Wifi { mqtt: true, .. })
|
"",
|
||||||
.to_string()
|
)
|
||||||
.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
|
||||||
@@ -337,14 +320,10 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
}
|
}
|
||||||
wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await;
|
wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await;
|
||||||
} else {
|
} else {
|
||||||
LOG_ACCESS
|
log(LogMessage::NormalRun, 0, 0, "", "").await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::NormalRun, 0, 0, "", "")
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dry_run = false;
|
let dry_run = MQTT_STAY_ALIVE.load(Ordering::Relaxed);
|
||||||
|
|
||||||
let tank_state = determine_tank_state(&mut board).await;
|
let tank_state = determine_tank_state(&mut board).await;
|
||||||
|
|
||||||
@@ -353,37 +332,20 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
match err {
|
match err {
|
||||||
TankError::SensorDisabled => { /* unreachable */ }
|
TankError::SensorDisabled => { /* unreachable */ }
|
||||||
TankError::SensorMissing(raw_value_mv) => {
|
TankError::SensorMissing(raw_value_mv) => {
|
||||||
LOG_ACCESS
|
log(LogMessage::TankSensorMissing, raw_value_mv as u32, 0, "", "").await
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(
|
|
||||||
LogMessage::TankSensorMissing,
|
|
||||||
raw_value_mv as u32,
|
|
||||||
0,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
TankError::SensorValueError { value, min, max } => {
|
TankError::SensorValueError { value, min, max } => {
|
||||||
LOG_ACCESS
|
log(
|
||||||
.lock()
|
LogMessage::TankSensorValueRangeError,
|
||||||
.await
|
min as u32,
|
||||||
.log(
|
max as u32,
|
||||||
LogMessage::TankSensorValueRangeError,
|
&format!("{value}"),
|
||||||
min as u32,
|
"",
|
||||||
max as u32,
|
)
|
||||||
&format!("{value}"),
|
.await
|
||||||
"",
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
TankError::BoardError(err) => {
|
TankError::BoardError(err) => {
|
||||||
LOG_ACCESS
|
log(LogMessage::TankSensorBoardError, 0, 0, "", &err.to_string()).await
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::TankSensorBoardError, 0, 0, "", &err.to_string())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// disabled cannot trigger this because of wrapping if is_enabled
|
// disabled cannot trigger this because of wrapping if is_enabled
|
||||||
@@ -392,11 +354,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
.warn_level(&board.board_hal.get_config().tank)
|
.warn_level(&board.board_hal.get_config().tank)
|
||||||
.is_ok_and(|warn| warn)
|
.is_ok_and(|warn| warn)
|
||||||
{
|
{
|
||||||
LOG_ACCESS
|
log(LogMessage::TankWaterLevelLow, 0, 0, "", "").await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::TankWaterLevelLow, 0, 0, "", "")
|
|
||||||
.await;
|
|
||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,11 +403,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
.any(|(it, conf)| it.needs_to_be_watered(conf, &timezone_time))
|
.any(|(it, conf)| it.needs_to_be_watered(conf, &timezone_time))
|
||||||
&& !water_frozen;
|
&& !water_frozen;
|
||||||
if pump_required {
|
if pump_required {
|
||||||
LOG_ACCESS
|
log(LogMessage::EnableMain, dry_run as u32, 0, "", "").await;
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.log(LogMessage::EnableMain, dry_run as u32, 0, "", "")
|
|
||||||
.await;
|
|
||||||
for (plant_id, (state, plant_config)) in plantstate
|
for (plant_id, (state, plant_config)) in plantstate
|
||||||
.iter()
|
.iter()
|
||||||
.zip(&board.board_hal.get_config().plants.clone())
|
.zip(&board.board_hal.get_config().plants.clone())
|
||||||
@@ -489,12 +443,13 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
board.board_hal.get_esp().last_pump_time(plant_id);
|
board.board_hal.get_esp().last_pump_time(plant_id);
|
||||||
//state.active = true;
|
//state.active = true;
|
||||||
|
|
||||||
pump_info(plant_id, true, pump_ineffective, 0, 0, 0, false).await;
|
pump_info(&mut board, plant_id, true, pump_ineffective, 0, 0, 0, false).await;
|
||||||
|
|
||||||
let result = do_secure_pump(&mut board, plant_id, plant_config, dry_run).await?;
|
let result = do_secure_pump(&mut board, plant_id, plant_config, dry_run).await?;
|
||||||
//stop pump regardless of prior result//todo refactor to inner?
|
//stop pump regardless of prior result//todo refactor to inner?
|
||||||
board.board_hal.pump(plant_id, false).await?;
|
board.board_hal.pump(plant_id, false).await?;
|
||||||
pump_info(
|
pump_info(
|
||||||
|
&mut board,
|
||||||
plant_id,
|
plant_id,
|
||||||
false,
|
false,
|
||||||
pump_ineffective,
|
pump_ineffective,
|
||||||
@@ -947,6 +902,7 @@ async fn try_connect_wifi_sntp_mqtt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn pump_info(
|
async fn pump_info(
|
||||||
|
board: &mut MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>,
|
||||||
plant_id: usize,
|
plant_id: usize,
|
||||||
pump_active: bool,
|
pump_active: bool,
|
||||||
pump_ineffective: bool,
|
pump_ineffective: bool,
|
||||||
@@ -966,15 +922,7 @@ async fn pump_info(
|
|||||||
|
|
||||||
match serde_json::to_string(&pump_info) {
|
match serde_json::to_string(&pump_info) {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
BOARD_ACCESS
|
board.board_hal.get_esp().mqtt_publish(&pump_topic, &state).await;
|
||||||
.get()
|
|
||||||
.await
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.board_hal
|
|
||||||
.get_esp()
|
|
||||||
.mqtt_publish(&pump_topic, &state)
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("Error publishing pump state {err}");
|
warn!("Error publishing pump state {err}");
|
||||||
@@ -1222,6 +1170,7 @@ use embassy_time::WithTimeout;
|
|||||||
async fn main(spawner: Spawner) -> ! {
|
async fn main(spawner: Spawner) -> ! {
|
||||||
// intialize embassy
|
// intialize embassy
|
||||||
logger::init_logger_from_env();
|
logger::init_logger_from_env();
|
||||||
|
spawner.must_spawn(crate::log::log_task());
|
||||||
//force init here!
|
//force init here!
|
||||||
match BOARD_ACCESS.init(
|
match BOARD_ACCESS.init(
|
||||||
PlantHal::create()
|
PlantHal::create()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::fat_error::{FatError, FatResult};
|
use crate::fat_error::{FatError, FatResult};
|
||||||
use crate::hal::{esp_time, PLANT_COUNT};
|
use crate::hal::PLANT_COUNT;
|
||||||
use crate::log::LogMessage;
|
use crate::log::LogMessage;
|
||||||
use crate::plant_state::{MoistureSensorState, PlantState};
|
use crate::plant_state::{MoistureSensorState, PlantState};
|
||||||
use crate::tank::determine_tank_state;
|
use crate::tank::determine_tank_state;
|
||||||
@@ -174,7 +174,7 @@ pub(crate) async fn get_time<T, const N: usize>(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let native = esp_time().await.with_timezone(&tz).to_rfc3339();
|
let native = board.board_hal.get_time().await.with_timezone(&tz).to_rfc3339();
|
||||||
|
|
||||||
let rtc = match board.board_hal.get_rtc_module().get_rtc_time().await {
|
let rtc = match board.board_hal.get_rtc_module().get_rtc_time().await {
|
||||||
Ok(time) => time.with_timezone(&tz).to_rfc3339(),
|
Ok(time) => time.with_timezone(&tz).to_rfc3339(),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::config::PlantControllerConfig;
|
use crate::config::PlantControllerConfig;
|
||||||
use crate::fat_error::FatResult;
|
use crate::fat_error::FatResult;
|
||||||
use crate::hal::{esp_set_time, Detection};
|
use crate::hal::Detection;
|
||||||
use crate::webserver::read_up_to_bytes_from_request;
|
use crate::webserver::read_up_to_bytes_from_request;
|
||||||
use crate::{do_secure_pump, BOARD_ACCESS};
|
use crate::{do_secure_pump, BOARD_ACCESS};
|
||||||
use alloc::string::{String, ToString};
|
use alloc::string::{String, ToString};
|
||||||
@@ -109,7 +109,8 @@ where
|
|||||||
let actual_data = read_up_to_bytes_from_request(request, None).await?;
|
let actual_data = read_up_to_bytes_from_request(request, None).await?;
|
||||||
let time: SetTime = serde_json::from_slice(&actual_data)?;
|
let time: SetTime = serde_json::from_slice(&actual_data)?;
|
||||||
let parsed = DateTime::parse_from_rfc3339(time.time)?;
|
let parsed = DateTime::parse_from_rfc3339(time.time)?;
|
||||||
esp_set_time(parsed).await?;
|
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||||
|
board.board_hal.set_time(&parsed).await?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user