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::config::{NetworkConfig, PlantControllerConfig};
|
||||
use crate::hal::savegame_manager::SavegameManager;
|
||||
use crate::hal::{PLANT_COUNT, TIME_ACCESS};
|
||||
use crate::log::{LogMessage, LOG_ACCESS};
|
||||
use crate::hal::PLANT_COUNT;
|
||||
use crate::log::{log, LogMessage};
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||
@@ -16,7 +16,7 @@ use embassy_executor::Spawner;
|
||||
use embassy_net::udp::UdpSocket;
|
||||
use embassy_net::{DhcpConfig, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||
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_time::{Duration, Timer, WithTimeout};
|
||||
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 uart0: Uart<'a, Blocking>,
|
||||
|
||||
pub rtc: Rtc<'a>,
|
||||
|
||||
pub ota: Ota<'static, RmwNorFlashStorage<'static, &'static mut MutexFlashStorage>>,
|
||||
pub ota_target: &'static mut FlashRegion<'static, MutexFlashStorage>,
|
||||
pub current: AppPartitionSubType,
|
||||
@@ -137,6 +139,14 @@ macro_rules! mk_static {
|
||||
}
|
||||
|
||||
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>> {
|
||||
let mut buf = [0u8; 1];
|
||||
let mut line = String::new();
|
||||
@@ -442,70 +452,65 @@ impl Esp<'_> {
|
||||
spawner.spawn(net_task(runner)).ok();
|
||||
self.controller.lock().await.start_async().await?;
|
||||
|
||||
let timeout = {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} + max_wait as u64 * 1000;
|
||||
loop {
|
||||
let state = esp_radio::wifi::sta_state();
|
||||
if state == WifiStaState::Started {
|
||||
self.controller.lock().await.connect()?;
|
||||
break;
|
||||
let res = async {
|
||||
loop {
|
||||
let state = esp_radio::wifi::sta_state();
|
||||
if state == WifiStaState::Started {
|
||||
self.controller.lock().await.connect()?;
|
||||
break;
|
||||
}
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
if {
|
||||
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;
|
||||
Ok::<(), FatError>(())
|
||||
}
|
||||
let timeout = {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} + max_wait as u64 * 1000;
|
||||
loop {
|
||||
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;
|
||||
.with_timeout(Duration::from_millis(max_wait as u64 * 1000))
|
||||
.await;
|
||||
|
||||
if res.is_err() {
|
||||
bail!("Timeout waiting for wifi sta ready")
|
||||
}
|
||||
let timeout = {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} + max_wait as u64 * 1000;
|
||||
while !stack.is_link_up() {
|
||||
if {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} > timeout
|
||||
{
|
||||
bail!("Timeout waiting for wifi link up")
|
||||
|
||||
let res = async {
|
||||
loop {
|
||||
let state = esp_radio::wifi::sta_state();
|
||||
if state == WifiStaState::Connected {
|
||||
break;
|
||||
}
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
Ok::<(), FatError>(())
|
||||
}
|
||||
let timeout = {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} + max_wait as u64 * 1000;
|
||||
while !stack.is_config_up() {
|
||||
if {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} > timeout
|
||||
{
|
||||
bail!("Timeout waiting for wifi config up")
|
||||
.with_timeout(Duration::from_millis(max_wait as u64 * 1000))
|
||||
.await;
|
||||
|
||||
if res.is_err() {
|
||||
bail!("Timeout waiting for wifi sta connected")
|
||||
}
|
||||
|
||||
let res = async {
|
||||
while !stack.is_link_up() {
|
||||
Timer::after(Duration::from_millis(500)).await;
|
||||
}
|
||||
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());
|
||||
@@ -515,7 +520,6 @@ impl Esp<'_> {
|
||||
pub fn deep_sleep(
|
||||
&mut self,
|
||||
duration_in_ms: u64,
|
||||
mut rtc: MutexGuard<CriticalSectionRawMutex, Rtc>,
|
||||
) -> ! {
|
||||
// Mark the current OTA image as valid if we reached here while in pending verify.
|
||||
if let Ok(cur) = self.ota.current_ota_state() {
|
||||
@@ -536,7 +540,7 @@ impl Esp<'_> {
|
||||
let mut wake_pins: [(&mut dyn RtcPinWithResistors, WakeupLevel); 1] =
|
||||
[(&mut self.wake_gpio1, WakeupLevel::Low)];
|
||||
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 {
|
||||
RESTART_TO_CONF = 1;
|
||||
}
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::RestartToConfig,
|
||||
RESTART_TO_CONF as u32,
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::LowVoltage,
|
||||
LOW_VOLTAGE_DETECTED as u32,
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
log(LogMessage::RestartToConfig, RESTART_TO_CONF as u32, 0, "", "").await;
|
||||
log(
|
||||
LogMessage::LowVoltage,
|
||||
LOW_VOLTAGE_DETECTED as u32,
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
// is executed before main, no other code will alter these values during printing
|
||||
#[allow(static_mut_refs)]
|
||||
for (i, time) in LAST_WATERING_TIMESTAMP.iter().enumerate() {
|
||||
@@ -703,29 +694,22 @@ impl Esp<'_> {
|
||||
))?;
|
||||
spawner.spawn(mqtt_runner(task))?;
|
||||
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::StayAlive, 0, 0, "", &stay_alive_topic)
|
||||
.await;
|
||||
log(LogMessage::StayAlive, 0, 0, "", &stay_alive_topic).await;
|
||||
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::MqttInfo, 0, 0, "", mqtt_url)
|
||||
.await;
|
||||
log(LogMessage::MqttInfo, 0, 0, "", mqtt_url).await;
|
||||
|
||||
let mqtt_timeout = 15000;
|
||||
let timeout = {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} + 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")
|
||||
let res = async {
|
||||
while !MQTT_CONNECTED_EVENT_RECEIVED.load(Ordering::Relaxed) {
|
||||
Timer::after(Duration::from_millis(100)).await;
|
||||
}
|
||||
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())
|
||||
@@ -733,18 +717,19 @@ impl Esp<'_> {
|
||||
.publish()
|
||||
.await;
|
||||
|
||||
let timeout = {
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
} + 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")
|
||||
let res = async {
|
||||
while !MQTT_ROUND_TRIP_RECEIVED.load(Ordering::Relaxed) {
|
||||
Timer::after(Duration::from_millis(100)).await;
|
||||
}
|
||||
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(())
|
||||
}
|
||||
@@ -851,18 +836,10 @@ async fn mqtt_incoming_task(
|
||||
true => 1,
|
||||
false => 0,
|
||||
};
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::MqttStayAliveRec, a, 0, "", "")
|
||||
.await;
|
||||
log(LogMessage::MqttStayAliveRec, a, 0, "", "").await;
|
||||
MQTT_STAY_ALIVE.store(value, Ordering::Relaxed);
|
||||
} else {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::UnknownTopic, 0, 0, "", &topic)
|
||||
.await;
|
||||
log(LogMessage::UnknownTopic, 0, 0, "", &topic).await;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -44,8 +44,8 @@ use crate::{
|
||||
battery::{BatteryInteraction, NoBatteryMonitor},
|
||||
esp::Esp,
|
||||
},
|
||||
log::log,
|
||||
log::LogMessage,
|
||||
BOARD_ACCESS,
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::format;
|
||||
@@ -77,7 +77,6 @@ use crate::fat_error::{ContextExt, FatError, FatResult};
|
||||
use crate::hal::battery::WCHI2CSlave;
|
||||
use crate::hal::savegame_manager::SavegameManager;
|
||||
use crate::hal::water::TankSensor;
|
||||
use crate::log::LOG_ACCESS;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use embassy_sync::once_lock::OnceLock;
|
||||
use embedded_storage::nor_flash::RmwNorFlashStorage;
|
||||
@@ -104,8 +103,6 @@ use portable_atomic::AtomicBool;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use shared_flash::MutexFlashStorage;
|
||||
|
||||
pub static TIME_ACCESS: OnceLock<Mutex<CriticalSectionRawMutex, Rtc>> = OnceLock::new();
|
||||
|
||||
//Only support for 8 right now!
|
||||
pub const PLANT_COUNT: usize = 8;
|
||||
|
||||
@@ -145,6 +142,8 @@ pub trait BoardInteraction<'a> {
|
||||
fn get_config(&mut self) -> &PlantControllerConfig;
|
||||
fn get_battery_monitor(&mut self) -> &mut Box<dyn BatteryInteraction + 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 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!(#[link_section = ".dram2_uninit"] size: 64000);
|
||||
|
||||
let rtc: Rtc = Rtc::new(peripherals.LPWR);
|
||||
TIME_ACCESS
|
||||
.init(Mutex::new(rtc))
|
||||
.map_err(|_| FatError::String {
|
||||
error: "Init error rct".to_string(),
|
||||
})?;
|
||||
let rtc_peripheral: Rtc = Rtc::new(peripherals.LPWR);
|
||||
|
||||
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||
let sw_int = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
||||
@@ -409,6 +403,7 @@ impl PlantHal {
|
||||
slot0_state: state_0,
|
||||
slot1_state: state_1,
|
||||
uart0,
|
||||
rtc: rtc_peripheral,
|
||||
};
|
||||
|
||||
//init,reset rtc memory depending on cause
|
||||
@@ -444,17 +439,14 @@ impl PlantHal {
|
||||
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;
|
||||
log(
|
||||
LogMessage::ResetReason,
|
||||
init_rtc_store as u32,
|
||||
to_config_mode as u32,
|
||||
"",
|
||||
&format!("{reasons:?}"),
|
||||
)
|
||||
.await;
|
||||
|
||||
esp.init_rtc_deepsleep_memory(init_rtc_store, to_config_mode)
|
||||
.await;
|
||||
@@ -548,17 +540,14 @@ impl PlantHal {
|
||||
HAL { board_hal }
|
||||
}
|
||||
Err(err) => {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::ConfigModeMissingConfig,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
&err.to_string(),
|
||||
)
|
||||
.await;
|
||||
log(
|
||||
LogMessage::ConfigModeMissingConfig,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
&err.to_string(),
|
||||
)
|
||||
.await;
|
||||
HAL {
|
||||
board_hal: v4_hal::create_v4(
|
||||
free_pins,
|
||||
@@ -641,27 +630,6 @@ pub fn next_partition(current: AppPartitionSubType) -> FatResult<AppPartitionSub
|
||||
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)]
|
||||
pub struct Moistures {
|
||||
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::{
|
||||
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::string::ToString;
|
||||
use async_trait::async_trait;
|
||||
use bincode::config;
|
||||
use canapi::id::{classify, plant_id, MessageKind, IDENTIFY_CMD_OFFSET};
|
||||
use canapi::SensorSlot;
|
||||
use chrono::{DateTime, FixedOffset, Utc};
|
||||
use core::cmp::min;
|
||||
use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
@@ -300,6 +300,16 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
&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> {
|
||||
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) -> ! {
|
||||
self.awake.set_low();
|
||||
self.charger.power_save();
|
||||
let rtc = TIME_ACCESS.get().await.lock().await;
|
||||
self.esp.deep_sleep(duration_in_ms, rtc);
|
||||
self.esp.deep_sleep(duration_in_ms);
|
||||
}
|
||||
|
||||
fn is_day(&self) -> bool {
|
||||
@@ -507,10 +516,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||
for plant in 0..PLANT_COUNT {
|
||||
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;
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::TestSensor, a, b, &(plant + 1).to_string(), "")
|
||||
log(LogMessage::TestSensor, a, b, &(plant + 1).to_string(), "")
|
||||
.await;
|
||||
}
|
||||
Timer::after_millis(10).await;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use crate::hal::TIME_ACCESS;
|
||||
use crate::BOARD_ACCESS;
|
||||
use crate::vec;
|
||||
use alloc::string::ToString;
|
||||
use alloc::vec::Vec;
|
||||
use bytemuck::{AnyBitPattern, Pod, Zeroable};
|
||||
use deranged::RangedU8;
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::channel::Channel;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use esp_hal::Persistable;
|
||||
use log::{info, warn};
|
||||
@@ -32,6 +33,34 @@ static mut LOG_ARRAY: LogArray = LogArray {
|
||||
pub static LOG_ACCESS: Mutex<CriticalSectionRawMutex, &'static mut LogArray> =
|
||||
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_LONG_LENGTH: usize = 32;
|
||||
|
||||
@@ -87,11 +116,21 @@ pub async fn log(
|
||||
txt_short: &str,
|
||||
txt_long: &str,
|
||||
) {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(message_key, number_a, number_b, txt_short, txt_long)
|
||||
.await
|
||||
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);
|
||||
|
||||
LOG_CHANNEL
|
||||
.send(LogRequest {
|
||||
message_key,
|
||||
number_a,
|
||||
number_b,
|
||||
txt_short: txt_short_stack,
|
||||
txt_long: txt_long_stack,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
impl LogArray {
|
||||
@@ -122,15 +161,9 @@ impl LogArray {
|
||||
let mut head: RangedU8<0, MAX_LOG_ARRAY_INDEX> =
|
||||
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 guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.current_time_us()
|
||||
let mut guard = BOARD_ACCESS.get().await.lock().await;
|
||||
guard.board_hal.get_esp().rtc.current_time_us()
|
||||
} / 1000;
|
||||
|
||||
let ordinal = message_key.ordinal() as u16;
|
||||
@@ -148,12 +181,8 @@ impl LogArray {
|
||||
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());
|
||||
to_modify.txt_short.clone_from_slice(txt_short.as_bytes());
|
||||
to_modify.txt_long.clone_from_slice(txt_long.as_bytes());
|
||||
head = head.wrapping_add(1);
|
||||
self.head = head.get();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ use crate::config::{NetworkConfig, PlantConfig, PlantControllerConfig};
|
||||
use crate::fat_error::FatResult;
|
||||
use crate::hal::esp::MQTT_STAY_ALIVE;
|
||||
use crate::hal::PROGRESS_ACTIVE;
|
||||
use crate::hal::{esp_time, TIME_ACCESS};
|
||||
use crate::log::{log, LOG_ACCESS};
|
||||
use crate::log::log;
|
||||
use crate::tank::{determine_tank_state, TankError, TankState, WATER_FROZEN_THRESH};
|
||||
use crate::webserver::http_server;
|
||||
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 {
|
||||
Ok(value) => {
|
||||
{
|
||||
let guard = TIME_ACCESS.get().await.lock().await;
|
||||
guard.set_current_time_us(value.timestamp_micros() as u64);
|
||||
board.board_hal.get_esp().rtc.set_current_time_us(value.timestamp_micros() as u64);
|
||||
}
|
||||
value
|
||||
}
|
||||
Err(err) => {
|
||||
info!("rtc module error: {err:?}");
|
||||
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)
|
||||
if cur.year() < 2020 {
|
||||
to_config = true;
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "")
|
||||
.await;
|
||||
log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "").await;
|
||||
}
|
||||
info!("cur is {cur}");
|
||||
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() {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "")
|
||||
.await;
|
||||
log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "").await;
|
||||
for _i in 0..2 {
|
||||
board.board_hal.general_fault(true).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);
|
||||
} else if board.board_hal.get_esp().mode_override_pressed() {
|
||||
board.board_hal.general_fault(true).await;
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "")
|
||||
.await;
|
||||
log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "").await;
|
||||
for _i in 0..5 {
|
||||
board.board_hal.general_fault(true).await;
|
||||
Timer::after_millis(100).await;
|
||||
@@ -304,25 +290,22 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
let _ = publish_mppt_state(&mut board).await;
|
||||
}
|
||||
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::StartupInfo,
|
||||
matches!(network_mode, NetworkMode::Wifi { .. }) as u32,
|
||||
matches!(
|
||||
network_mode,
|
||||
NetworkMode::Wifi {
|
||||
sntp: SntpMode::Sync { .. },
|
||||
..
|
||||
}
|
||||
) as u32,
|
||||
matches!(network_mode, NetworkMode::Wifi { mqtt: true, .. })
|
||||
.to_string()
|
||||
.as_str(),
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
log(
|
||||
LogMessage::StartupInfo,
|
||||
matches!(network_mode, NetworkMode::Wifi { .. }) as u32,
|
||||
matches!(
|
||||
network_mode,
|
||||
NetworkMode::Wifi {
|
||||
sntp: SntpMode::Sync { .. },
|
||||
..
|
||||
}
|
||||
) as u32,
|
||||
matches!(network_mode, NetworkMode::Wifi { mqtt: true, .. })
|
||||
.to_string()
|
||||
.as_str(),
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
|
||||
if to_config {
|
||||
//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;
|
||||
} else {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::NormalRun, 0, 0, "", "")
|
||||
.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;
|
||||
|
||||
@@ -353,37 +332,20 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
||||
match err {
|
||||
TankError::SensorDisabled => { /* unreachable */ }
|
||||
TankError::SensorMissing(raw_value_mv) => {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::TankSensorMissing,
|
||||
raw_value_mv as u32,
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
)
|
||||
.await
|
||||
log(LogMessage::TankSensorMissing, raw_value_mv as u32, 0, "", "").await
|
||||
}
|
||||
TankError::SensorValueError { value, min, max } => {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(
|
||||
LogMessage::TankSensorValueRangeError,
|
||||
min as u32,
|
||||
max as u32,
|
||||
&format!("{value}"),
|
||||
"",
|
||||
)
|
||||
.await
|
||||
log(
|
||||
LogMessage::TankSensorValueRangeError,
|
||||
min as u32,
|
||||
max as u32,
|
||||
&format!("{value}"),
|
||||
"",
|
||||
)
|
||||
.await
|
||||
}
|
||||
TankError::BoardError(err) => {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::TankSensorBoardError, 0, 0, "", &err.to_string())
|
||||
.await
|
||||
log(LogMessage::TankSensorBoardError, 0, 0, "", &err.to_string()).await
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
.is_ok_and(|warn| warn)
|
||||
{
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::TankWaterLevelLow, 0, 0, "", "")
|
||||
.await;
|
||||
log(LogMessage::TankWaterLevelLow, 0, 0, "", "").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))
|
||||
&& !water_frozen;
|
||||
if pump_required {
|
||||
LOG_ACCESS
|
||||
.lock()
|
||||
.await
|
||||
.log(LogMessage::EnableMain, dry_run as u32, 0, "", "")
|
||||
.await;
|
||||
log(LogMessage::EnableMain, dry_run as u32, 0, "", "").await;
|
||||
for (plant_id, (state, plant_config)) in plantstate
|
||||
.iter()
|
||||
.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);
|
||||
//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?;
|
||||
//stop pump regardless of prior result//todo refactor to inner?
|
||||
board.board_hal.pump(plant_id, false).await?;
|
||||
pump_info(
|
||||
&mut board,
|
||||
plant_id,
|
||||
false,
|
||||
pump_ineffective,
|
||||
@@ -947,6 +902,7 @@ async fn try_connect_wifi_sntp_mqtt(
|
||||
}
|
||||
|
||||
async fn pump_info(
|
||||
board: &mut MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>,
|
||||
plant_id: usize,
|
||||
pump_active: bool,
|
||||
pump_ineffective: bool,
|
||||
@@ -966,15 +922,7 @@ async fn pump_info(
|
||||
|
||||
match serde_json::to_string(&pump_info) {
|
||||
Ok(state) => {
|
||||
BOARD_ACCESS
|
||||
.get()
|
||||
.await
|
||||
.lock()
|
||||
.await
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.mqtt_publish(&pump_topic, &state)
|
||||
.await;
|
||||
board.board_hal.get_esp().mqtt_publish(&pump_topic, &state).await;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Error publishing pump state {err}");
|
||||
@@ -1222,6 +1170,7 @@ use embassy_time::WithTimeout;
|
||||
async fn main(spawner: Spawner) -> ! {
|
||||
// intialize embassy
|
||||
logger::init_logger_from_env();
|
||||
spawner.must_spawn(crate::log::log_task());
|
||||
//force init here!
|
||||
match BOARD_ACCESS.init(
|
||||
PlantHal::create()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::fat_error::{FatError, FatResult};
|
||||
use crate::hal::{esp_time, PLANT_COUNT};
|
||||
use crate::hal::PLANT_COUNT;
|
||||
use crate::log::LogMessage;
|
||||
use crate::plant_state::{MoistureSensorState, PlantState};
|
||||
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 {
|
||||
Ok(time) => time.with_timezone(&tz).to_rfc3339(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::config::PlantControllerConfig;
|
||||
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::{do_secure_pump, BOARD_ACCESS};
|
||||
use alloc::string::{String, ToString};
|
||||
@@ -109,7 +109,8 @@ where
|
||||
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)?;
|
||||
esp_set_time(parsed).await?;
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
board.board_hal.set_time(&parsed).await?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user