logging and pcb adjustment
This commit is contained in:
parent
1741bb0b53
commit
aad1dbd458
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"board": {
|
"board": {
|
||||||
"active_layer": 37,
|
"active_layer": 31,
|
||||||
"active_layer_preset": "",
|
"active_layer_preset": "",
|
||||||
"auto_track_width": false,
|
"auto_track_width": false,
|
||||||
"hidden_netclasses": [],
|
"hidden_netclasses": [],
|
||||||
|
@ -17378,6 +17378,16 @@
|
|||||||
)
|
)
|
||||||
(uuid "3279e749-d62b-45dc-920c-a4d4fc61f21f")
|
(uuid "3279e749-d62b-45dc-920c-a4d4fc61f21f")
|
||||||
)
|
)
|
||||||
|
(text "use around 33k for 17.1v\nbe aware limit is 6v on input pin!"
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(at 387.096 525.526 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(uuid "3455ce77-4a9f-487a-85c9-d8775331bede")
|
||||||
|
)
|
||||||
(text "WaterTemp"
|
(text "WaterTemp"
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(at 74.93 194.31 0)
|
(at 74.93 194.31 0)
|
||||||
|
File diff suppressed because one or more lines are too long
@ -28,7 +28,9 @@ command = [
|
|||||||
"save-image",
|
"save-image",
|
||||||
"--chip",
|
"--chip",
|
||||||
"esp32c6",
|
"esp32c6",
|
||||||
"image.bin"
|
"image.bin",
|
||||||
|
"--partition-table",
|
||||||
|
"partitions.csv"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -66,7 +68,7 @@ once_cell = "1.19.0"
|
|||||||
anyhow = { version = "1.0.75", features = ["std", "backtrace"] }
|
anyhow = { version = "1.0.75", features = ["std", "backtrace"] }
|
||||||
average = { version = "0.14.1" , features = ["std"] }
|
average = { version = "0.14.1" , features = ["std"] }
|
||||||
bit_field = "0.10.2"
|
bit_field = "0.10.2"
|
||||||
strum = { version = "0.26.1", features = ["derive"] }
|
strum = { version = "0.27.0", features = ["derive"] }
|
||||||
measurements = "0.11.0"
|
measurements = "0.11.0"
|
||||||
schemars = "0.8.16"
|
schemars = "0.8.16"
|
||||||
|
|
||||||
@ -82,6 +84,8 @@ url = "2.5.3"
|
|||||||
crc = "3.2.1"
|
crc = "3.2.1"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
ringbuffer = "0.15.0"
|
ringbuffer = "0.15.0"
|
||||||
|
text-template = "0.1.0"
|
||||||
|
strum_macros = "0.27.0"
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
143
rust/src/log/mod.rs
Normal file
143
rust/src/log/mod.rs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
use std::{collections::HashMap, sync::Mutex};
|
||||||
|
use strum_macros::IntoStaticStr;
|
||||||
|
|
||||||
|
use esp_idf_svc::systime::EspSystemTime;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
|
||||||
|
use text_template::Template;
|
||||||
|
|
||||||
|
const TXT_SHORT_LENGTH:usize = 8;
|
||||||
|
const TXT_LONG_LENGTH:usize = 32;
|
||||||
|
|
||||||
|
const BUFFER_SIZE:usize = 210;
|
||||||
|
|
||||||
|
#[link_section = ".rtc.data"]
|
||||||
|
static mut BUFFER:ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE> = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
||||||
|
|
||||||
|
static BUFFER_ACCESS: Lazy<Mutex<&mut ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>>> = Lazy::new(|| unsafe { Mutex::new(&mut BUFFER) });
|
||||||
|
|
||||||
|
|
||||||
|
pub struct LogEntry {
|
||||||
|
pub timestamp: u64,
|
||||||
|
pub message_id: u32,
|
||||||
|
pub a: u32,
|
||||||
|
pub b: u32,
|
||||||
|
pub txt_short: heapless::String<TXT_SHORT_LENGTH>,
|
||||||
|
pub txt_long: heapless::String<TXT_LONG_LENGTH>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init(){
|
||||||
|
unsafe {
|
||||||
|
BUFFER = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
||||||
|
};
|
||||||
|
let mut access = BUFFER_ACCESS.lock().unwrap();
|
||||||
|
access.drain().for_each(|_| {});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn limit_length <const LIMIT:usize> (input: &str, target: &mut heapless::String<LIMIT>){
|
||||||
|
for char in input.chars() {
|
||||||
|
match target.push(char) {
|
||||||
|
Ok(_) => {}, //continue adding chars
|
||||||
|
Err(_) => {
|
||||||
|
//clear space for two asci chars
|
||||||
|
while target.len()+2 >= LIMIT {
|
||||||
|
target.pop().unwrap();
|
||||||
|
}
|
||||||
|
//add .. to shortened strings
|
||||||
|
target.push('.').unwrap();
|
||||||
|
target.push('.').unwrap();
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub 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);
|
||||||
|
|
||||||
|
let time = EspSystemTime {}.now().as_millis() as u64;
|
||||||
|
|
||||||
|
let template_string:&str = message_key.into();
|
||||||
|
|
||||||
|
|
||||||
|
let mut values: HashMap<&str, &str> = HashMap::new();
|
||||||
|
let number_a_str = number_a.to_string();
|
||||||
|
let number_b_str = number_b.to_string();
|
||||||
|
|
||||||
|
values.insert("number_a", &number_a_str);
|
||||||
|
values.insert("number_b", &number_b_str);
|
||||||
|
values.insert("txt_short", txt_short);
|
||||||
|
values.insert("txt_long", txt_long);
|
||||||
|
|
||||||
|
let template = Template::from(template_string);
|
||||||
|
let serial_entry = template.fill_in(&values);
|
||||||
|
|
||||||
|
println!("{serial_entry}");
|
||||||
|
|
||||||
|
|
||||||
|
let entry = LogEntry{
|
||||||
|
timestamp: time,
|
||||||
|
message_id: 1,
|
||||||
|
a: number_a,
|
||||||
|
b: number_b,
|
||||||
|
txt_short: txt_short_stack,
|
||||||
|
txt_long: txt_long_stack,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let mut buffer = BUFFER_ACCESS.lock().unwrap();
|
||||||
|
buffer.push(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn within_limit() {
|
||||||
|
let test = "12345678";
|
||||||
|
|
||||||
|
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(test, &mut txt_short_stack);
|
||||||
|
limit_length(test, &mut txt_long_stack);
|
||||||
|
|
||||||
|
assert_eq!(txt_short_stack.as_str(), test);
|
||||||
|
assert_eq!(txt_long_stack.as_str(), test);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(IntoStaticStr)]
|
||||||
|
pub enum LogMessage {
|
||||||
|
#[strum(serialize = "Reset due to {{txt_long}} requires rtc clear {{a}} and force config mode {{b}}")]
|
||||||
|
reset_reason,
|
||||||
|
#[strum(serialize = "Current restart to conf mode {{a}}")]
|
||||||
|
restart_to_config,
|
||||||
|
#[strum(serialize = "Current low voltage detection is {{a}}")]
|
||||||
|
low_voltage,
|
||||||
|
#[strum(serialize = "Error communicating with battery!! {{txt_long}}")]
|
||||||
|
battery_communication_error,
|
||||||
|
#[strum(serialize = "Tank sensor raw {{a}} percent {{b}}")]
|
||||||
|
sensor_tank_raw,
|
||||||
|
#[strum(serialize = "raw measure unscaled {{a}} hz {{b}}, plant {{txt_short}} sensor {{txt_long}}")]
|
||||||
|
raw_measure,
|
||||||
|
#[strum(serialize = "IP info: {{txt_long}}")]
|
||||||
|
wifi_info,
|
||||||
|
#[strum(serialize = "Plant:{{txt_short}} a:{{a}} b:{{b}}")]
|
||||||
|
test_sensor,
|
||||||
|
#[strum(serialize = "Stay alive topic is {{txt_long}}")]
|
||||||
|
stay_alive,
|
||||||
|
#[strum(serialize = "Connecting mqtt {{txt_short}} with id {{txt_long}}")]
|
||||||
|
mqtt_info,
|
||||||
|
#[strum(serialize = "Received stay alive with value {{txt_short}}")]
|
||||||
|
mqtt_stay_alive_rec,
|
||||||
|
#[strum(serialize = "Unknown topic recieved {{txt_long}}")]
|
||||||
|
unknown_topic,
|
||||||
|
}
|
@ -3,7 +3,7 @@ use std::{
|
|||||||
sync::{atomic::AtomicBool, Arc, Mutex},
|
sync::{atomic::AtomicBool, Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::{bail, Result};
|
||||||
use chrono::{DateTime, Datelike, TimeDelta, Timelike, Utc};
|
use chrono::{DateTime, Datelike, TimeDelta, Timelike, Utc};
|
||||||
use chrono_tz::{Europe::Berlin, Tz};
|
use chrono_tz::{Europe::Berlin, Tz};
|
||||||
|
|
||||||
@ -22,7 +22,6 @@ use esp_idf_sys::{
|
|||||||
esp_ota_img_states_t_ESP_OTA_IMG_VALID,
|
esp_ota_img_states_t_ESP_OTA_IMG_VALID,
|
||||||
vTaskDelay
|
vTaskDelay
|
||||||
};
|
};
|
||||||
use log::error;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use plant_hal::{PlantCtrlBoard, PlantHal, PLANT_COUNT};
|
use plant_hal::{PlantCtrlBoard, PlantHal, PLANT_COUNT};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -32,10 +31,12 @@ use crate::{
|
|||||||
espota::{mark_app_valid, rollback_and_reboot},
|
espota::{mark_app_valid, rollback_and_reboot},
|
||||||
webserver::webserver::httpd,
|
webserver::webserver::httpd,
|
||||||
};
|
};
|
||||||
|
mod log;
|
||||||
mod config;
|
mod config;
|
||||||
pub mod espota;
|
pub mod espota;
|
||||||
pub mod plant_hal;
|
pub mod plant_hal;
|
||||||
|
|
||||||
|
|
||||||
const TIME_ZONE: Tz = Berlin;
|
const TIME_ZONE: Tz = Berlin;
|
||||||
|
|
||||||
const MOIST_SENSOR_MAX_FREQUENCY: u32 = 250000; // 60kHz (500Hz margin)
|
const MOIST_SENSOR_MAX_FREQUENCY: u32 = 250000; // 60kHz (500Hz margin)
|
||||||
@ -72,9 +73,9 @@ struct LightState {
|
|||||||
#[derive(Debug, PartialEq, Default)]
|
#[derive(Debug, PartialEq, Default)]
|
||||||
struct PlantState {
|
struct PlantState {
|
||||||
a: Option<u8>,
|
a: Option<u8>,
|
||||||
a_raw: Option<i32>,
|
a_raw: Option<u32>,
|
||||||
b: Option<u8>,
|
b: Option<u8>,
|
||||||
b_raw: Option<i32>,
|
b_raw: Option<u32>,
|
||||||
consecutive_pump_count: u32,
|
consecutive_pump_count: u32,
|
||||||
after_p: Option<u8>,
|
after_p: Option<u8>,
|
||||||
do_water: bool,
|
do_water: bool,
|
||||||
@ -142,14 +143,14 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
esp_idf_svc::log::EspLogger::initialize_default();
|
esp_idf_svc::log::EspLogger::initialize_default();
|
||||||
|
|
||||||
if esp_idf_sys::CONFIG_MAIN_TASK_STACK_SIZE < 25000 {
|
if esp_idf_sys::CONFIG_MAIN_TASK_STACK_SIZE < 25000 {
|
||||||
error!(
|
bail!(
|
||||||
"stack too small: {} bail!",
|
"stack too small: {} bail!",
|
||||||
esp_idf_sys::CONFIG_MAIN_TASK_STACK_SIZE
|
esp_idf_sys::CONFIG_MAIN_TASK_STACK_SIZE
|
||||||
);
|
);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Startup Rust");
|
println!("Startup Rust");
|
||||||
|
|
||||||
let mut to_config = false;
|
let mut to_config = false;
|
||||||
|
|
||||||
@ -186,6 +187,7 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
};
|
};
|
||||||
println!("{}", ota_state_string);
|
println!("{}", ota_state_string);
|
||||||
|
|
||||||
|
|
||||||
println!("Board hal init");
|
println!("Board hal init");
|
||||||
let mut board: std::sync::MutexGuard<'_, PlantCtrlBoard<'_>> = BOARD_ACCESS.lock().unwrap();
|
let mut board: std::sync::MutexGuard<'_, PlantCtrlBoard<'_>> = BOARD_ACCESS.lock().unwrap();
|
||||||
board.general_fault(false);
|
board.general_fault(false);
|
||||||
@ -207,7 +209,7 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
match time {
|
match time {
|
||||||
Ok(cur) => cur,
|
Ok(cur) => cur,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("time error {}", err);
|
bail!("time error {}", err);
|
||||||
DateTime::from_timestamp_millis(0).unwrap()
|
DateTime::from_timestamp_millis(0).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,7 +286,7 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
ip_address = Some(ip_info.ip.to_string());
|
ip_address = Some(ip_info.ip.to_string());
|
||||||
wifi = true;
|
wifi = true;
|
||||||
|
|
||||||
match board.sntp(1000 * 5) {
|
match board.sntp(1000 * 10) {
|
||||||
Ok(new_time) => {
|
Ok(new_time) => {
|
||||||
println!("Using time from sntp");
|
println!("Using time from sntp");
|
||||||
let _ = board.set_rtc_time(&new_time);
|
let _ = board.set_rtc_time(&new_time);
|
||||||
|
@ -2,6 +2,7 @@ use bq34z100::{Bq34Z100Error, Bq34z100g1, Bq34z100g1Driver};
|
|||||||
|
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
use ds323x::{DateTimeAccess, Ds323x};
|
use ds323x::{DateTimeAccess, Ds323x};
|
||||||
|
use crate::log::{init, LogMessage};
|
||||||
|
|
||||||
use eeprom24x::{Eeprom24x, Eeprom24xTrait, SlaveAddr};
|
use eeprom24x::{Eeprom24x, Eeprom24xTrait, SlaveAddr};
|
||||||
use embedded_hal_bus::i2c::MutexDevice;
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
@ -22,6 +23,7 @@ use esp_idf_svc::mqtt::client::{EspMqttClient, LwtConfiguration, MqttClientConfi
|
|||||||
use esp_idf_svc::nvs::EspDefaultNvsPartition;
|
use esp_idf_svc::nvs::EspDefaultNvsPartition;
|
||||||
use esp_idf_svc::wifi::config::{ScanConfig, ScanType};
|
use esp_idf_svc::wifi::config::{ScanConfig, ScanType};
|
||||||
use esp_idf_svc::wifi::EspWifi;
|
use esp_idf_svc::wifi::EspWifi;
|
||||||
|
use log::logger;
|
||||||
use measurements::Temperature;
|
use measurements::Temperature;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use plant_ctrl2::sipo::ShiftRegister40;
|
use plant_ctrl2::sipo::ShiftRegister40;
|
||||||
@ -46,7 +48,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use embedded_hal::digital::OutputPin;
|
use embedded_hal::digital::OutputPin;
|
||||||
use esp_idf_hal::delay::Delay;
|
use esp_idf_hal::delay::Delay;
|
||||||
use esp_idf_hal::gpio::{AnyInputPin, Gpio18, Gpio5, Gpio7, Gpio8, IOPin, InputOutput, Level, PinDriver, Pull};
|
use esp_idf_hal::gpio::{AnyInputPin, Gpio18, Gpio5, IOPin, InputOutput, Level, PinDriver, Pull};
|
||||||
use esp_idf_hal::pcnt::{
|
use esp_idf_hal::pcnt::{
|
||||||
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
|
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
|
||||||
};
|
};
|
||||||
@ -54,11 +56,12 @@ use esp_idf_hal::prelude::Peripherals;
|
|||||||
use esp_idf_hal::reset::ResetReason;
|
use esp_idf_hal::reset::ResetReason;
|
||||||
use esp_idf_svc::sntp::{self, SyncStatus};
|
use esp_idf_svc::sntp::{self, SyncStatus};
|
||||||
use esp_idf_svc::systime::EspSystemTime;
|
use esp_idf_svc::systime::EspSystemTime;
|
||||||
use esp_idf_sys::{esp, esp_spiffs_check, gpio_hold_dis, gpio_hold_en, vTaskDelay, EspError};
|
use esp_idf_sys::{gpio_hold_dis, gpio_hold_en, vTaskDelay, EspError};
|
||||||
use one_wire_bus::OneWire;
|
use one_wire_bus::OneWire;
|
||||||
|
|
||||||
use crate::config::{self, PlantControllerConfig};
|
use crate::config::{self, PlantControllerConfig};
|
||||||
use crate::espota::mark_app_valid;
|
use crate::espota::mark_app_valid;
|
||||||
|
use crate::log::log;
|
||||||
use crate::{plant_hal, to_string, STAY_ALIVE};
|
use crate::{plant_hal, to_string, STAY_ALIVE};
|
||||||
|
|
||||||
//Only support for 8 right now!
|
//Only support for 8 right now!
|
||||||
@ -80,14 +83,15 @@ const PUMP5_BIT: usize = 5;
|
|||||||
const PUMP6_BIT: usize = 6;
|
const PUMP6_BIT: usize = 6;
|
||||||
const PUMP7_BIT: usize = 7;
|
const PUMP7_BIT: usize = 7;
|
||||||
|
|
||||||
|
|
||||||
const MS_0: usize = 8;
|
const MS_0: usize = 8;
|
||||||
const MS_4: usize = 9;
|
const MS_4: usize = 9;
|
||||||
const MS_2: usize = 10;
|
const MS_2: usize = 10;
|
||||||
const MS_3: usize = 11;
|
const MS_3: usize = 11;
|
||||||
const SENSOR_ON: usize = 12;
|
const SENSOR_ON: usize = 12;
|
||||||
const MS_1: usize = 13;
|
const MS_1: usize = 13;
|
||||||
//unused 14
|
const CHARGING: usize = 14;
|
||||||
//unused 15
|
const AWAKE: usize = 15;
|
||||||
|
|
||||||
const FAULT_3: usize = 16;
|
const FAULT_3: usize = 16;
|
||||||
const FAULT_8: usize = 17;
|
const FAULT_8: usize = 17;
|
||||||
@ -128,10 +132,6 @@ static mut LOW_VOLTAGE_DETECTED: bool = false;
|
|||||||
#[link_section = ".rtc.data"]
|
#[link_section = ".rtc.data"]
|
||||||
static mut RESTART_TO_CONF: bool = false;
|
static mut RESTART_TO_CONF: bool = false;
|
||||||
|
|
||||||
const BUFFER_SIZE:usize = 120;
|
|
||||||
const ENTRY_SIZE:usize = 120;
|
|
||||||
#[link_section = ".rtc.data"]
|
|
||||||
static mut BUFFER:ConstGenericRingBuffer::<heapless::String<ENTRY_SIZE>, BUFFER_SIZE> = ConstGenericRingBuffer::<heapless::String<ENTRY_SIZE>, BUFFER_SIZE>::new();
|
|
||||||
|
|
||||||
|
|
||||||
pub struct FileSystemSizeInfo {
|
pub struct FileSystemSizeInfo {
|
||||||
@ -266,9 +266,7 @@ impl PlantCtrlBoard<'_> {
|
|||||||
OkStd(_) => {},
|
OkStd(_) => {},
|
||||||
Err(err) => bail!("Error reading eeprom header {:?}", err),
|
Err(err) => bail!("Error reading eeprom header {:?}", err),
|
||||||
};
|
};
|
||||||
println!("Raw header is {:?} with size {}", header_page_buffer , store);
|
|
||||||
let header:BackupHeader = bincode::deserialize(&header_page_buffer)?;
|
let header:BackupHeader = bincode::deserialize(&header_page_buffer)?;
|
||||||
println!("Reading eeprom header {header:?}");
|
|
||||||
|
|
||||||
let data_start_address = 1*self.eeprom.page_size() as u32;
|
let data_start_address = 1*self.eeprom.page_size() as u32;
|
||||||
let mut data_buffer = vec![0_u8; header.size];
|
let mut data_buffer = vec![0_u8; header.size];
|
||||||
@ -282,19 +280,6 @@ impl PlantCtrlBoard<'_> {
|
|||||||
bail!("Invalid checksum, got {} but expected {}", checksum, header.crc16 );
|
bail!("Invalid checksum, got {} but expected {}", checksum, header.crc16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let value = heapless::String::try_from("dummy").unwrap();
|
|
||||||
BUFFER.push(value);
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
for entry in BUFFER.iter() {
|
|
||||||
let test = entry.as_bytes().to_owned();
|
|
||||||
for p in test {
|
|
||||||
data_buffer.push(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(data_buffer)
|
Ok(data_buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,9 +302,7 @@ impl PlantCtrlBoard<'_> {
|
|||||||
bail!("Size limit reached header is {}, but firest page is only {}",encoded.len(), page_size)
|
bail!("Size limit reached header is {}, but firest page is only {}",encoded.len(), page_size)
|
||||||
}
|
}
|
||||||
let as_u8:&[u8] = &encoded;
|
let as_u8:&[u8] = &encoded;
|
||||||
|
|
||||||
println!("Raw header is {:?} with size {}", as_u8 , as_u8.len());
|
|
||||||
|
|
||||||
match self.eeprom.write_page(0, as_u8) {
|
match self.eeprom.write_page(0, as_u8) {
|
||||||
OkStd(_) => {},
|
OkStd(_) => {},
|
||||||
Err(err) => bail!("Error writing eeprom {:?}", err),
|
Err(err) => bail!("Error writing eeprom {:?}", err),
|
||||||
@ -375,13 +358,11 @@ impl PlantCtrlBoard<'_> {
|
|||||||
let mut iter_error = None;
|
let mut iter_error = None;
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
|
|
||||||
println!("Filename {filename}");
|
|
||||||
let filepath = Path::new(BASE_PATH);
|
let filepath = Path::new(BASE_PATH);
|
||||||
let read_dir = fs::read_dir(filepath);
|
let read_dir = fs::read_dir(filepath);
|
||||||
match read_dir {
|
match read_dir {
|
||||||
OkStd(read_dir) => {
|
OkStd(read_dir) => {
|
||||||
for item in read_dir {
|
for item in read_dir {
|
||||||
println!("start loop");
|
|
||||||
match item {
|
match item {
|
||||||
OkStd(file) => {
|
OkStd(file) => {
|
||||||
let f = FileInfo {
|
let f = FileInfo {
|
||||||
@ -392,7 +373,6 @@ impl PlantCtrlBoard<'_> {
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
as usize,
|
as usize,
|
||||||
};
|
};
|
||||||
println!("fileinfo {f:?}");
|
|
||||||
result.push(f);
|
result.push(f);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@ -503,8 +483,8 @@ impl PlantCtrlBoard<'_> {
|
|||||||
let r2 = median * 50.0 / (3.3 - median);
|
let r2 = median * 50.0 / (3.3 - median);
|
||||||
let mut percent = r2 / 190_f32 * 100_f32;
|
let mut percent = r2 / 190_f32 * 100_f32;
|
||||||
percent = percent.clamp(0.0, 100.0);
|
percent = percent.clamp(0.0, 100.0);
|
||||||
|
log(LogMessage::sensor_tank_raw, median as u32, percent as u32, "","");
|
||||||
|
|
||||||
println!("Tank sensor raw {} percent {}", median, percent);
|
|
||||||
return Ok(percent as u16);
|
return Ok(percent as u16);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -620,7 +600,7 @@ impl PlantCtrlBoard<'_> {
|
|||||||
self.time()
|
self.time()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result<i32> {
|
pub fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result<u32> {
|
||||||
let sensor_channel = match sensor {
|
let sensor_channel = match sensor {
|
||||||
Sensor::A => match plant {
|
Sensor::A => match plant {
|
||||||
0 => SENSOR_A_1,
|
0 => SENSOR_A_1,
|
||||||
@ -646,7 +626,7 @@ impl PlantCtrlBoard<'_> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut results = [0; REPEAT_MOIST_MEASURE];
|
let mut results = [0_u32; REPEAT_MOIST_MEASURE];
|
||||||
for repeat in 0..REPEAT_MOIST_MEASURE {
|
for repeat in 0..REPEAT_MOIST_MEASURE {
|
||||||
self.signal_counter.counter_pause()?;
|
self.signal_counter.counter_pause()?;
|
||||||
self.signal_counter.counter_clear()?;
|
self.signal_counter.counter_clear()?;
|
||||||
@ -675,13 +655,9 @@ impl PlantCtrlBoard<'_> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
delay.delay_ms(10);
|
delay.delay_ms(10);
|
||||||
let unscaled = self.signal_counter.get_counter_value()? as i32;
|
let unscaled = self.signal_counter.get_counter_value()? as i32;
|
||||||
let hz = (unscaled as f32 * factor) as i32;
|
let hz = (unscaled as f32 * factor) as u32;
|
||||||
println!(
|
log(LogMessage::raw_measure, unscaled as u32, hz as u32, &plant.to_string(), &format!("{sensor:?}"));
|
||||||
"raw measure unscaled {} hz {}, plant {} sensor {:?}",
|
|
||||||
unscaled, hz, plant, sensor
|
|
||||||
);
|
|
||||||
results[repeat] = hz;
|
results[repeat] = hz;
|
||||||
//println!("Measuring {:?} @ {} with {}", sensor, plant, hz);
|
|
||||||
}
|
}
|
||||||
results.sort();
|
results.sort();
|
||||||
|
|
||||||
@ -745,7 +721,6 @@ impl PlantCtrlBoard<'_> {
|
|||||||
let delay = Delay::new_default();
|
let delay = Delay::new_default();
|
||||||
let mut counter = 0_u32;
|
let mut counter = 0_u32;
|
||||||
while !self.wifi_driver.is_connected()? {
|
while !self.wifi_driver.is_connected()? {
|
||||||
println!("Waiting for station connection");
|
|
||||||
delay.delay_ms(250);
|
delay.delay_ms(250);
|
||||||
counter += 250;
|
counter += 250;
|
||||||
if counter > max_wait {
|
if counter > max_wait {
|
||||||
@ -758,7 +733,6 @@ impl PlantCtrlBoard<'_> {
|
|||||||
println!("Should be connected now");
|
println!("Should be connected now");
|
||||||
|
|
||||||
while !self.wifi_driver.is_up()? {
|
while !self.wifi_driver.is_up()? {
|
||||||
println!("Waiting for network being up");
|
|
||||||
delay.delay_ms(250);
|
delay.delay_ms(250);
|
||||||
counter += 250;
|
counter += 250;
|
||||||
if counter > max_wait {
|
if counter > max_wait {
|
||||||
@ -770,7 +744,7 @@ impl PlantCtrlBoard<'_> {
|
|||||||
}
|
}
|
||||||
//update freertos registers ;)
|
//update freertos registers ;)
|
||||||
let address = self.wifi_driver.sta_netif().get_ip_info()?;
|
let address = self.wifi_driver.sta_netif().get_ip_info()?;
|
||||||
println!("IP info: {:?}", address);
|
log(LogMessage::wifi_info, 0 ,0,"", &format!("{address:?}"));
|
||||||
Ok(address)
|
Ok(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -908,9 +882,16 @@ impl PlantCtrlBoard<'_> {
|
|||||||
for plant in 0..PLANT_COUNT {
|
for plant in 0..PLANT_COUNT {
|
||||||
let a = self.measure_moisture_hz(plant, plant_hal::Sensor::A);
|
let a = self.measure_moisture_hz(plant, plant_hal::Sensor::A);
|
||||||
let b = self.measure_moisture_hz(plant, plant_hal::Sensor::B);
|
let b = self.measure_moisture_hz(plant, plant_hal::Sensor::B);
|
||||||
print!("P:{} a:{:?} b:{:?}", plant, a, b)
|
let aa = match a {
|
||||||
|
OkStd(a) => a as u32,
|
||||||
|
Err(_) => u32::MAX
|
||||||
|
};
|
||||||
|
let bb = match b {
|
||||||
|
OkStd(b) => b as u32,
|
||||||
|
Err(_) => u32::MAX
|
||||||
|
};
|
||||||
|
log(LogMessage::test_sensor, aa ,bb,&plant.to_string(), "");
|
||||||
}
|
}
|
||||||
println!();
|
|
||||||
Delay::new_default().delay_ms(10);
|
Delay::new_default().delay_ms(10);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -958,18 +939,15 @@ impl PlantCtrlBoard<'_> {
|
|||||||
let round_trip_ok = Arc::new(AtomicBool::new(false));
|
let round_trip_ok = Arc::new(AtomicBool::new(false));
|
||||||
let round_trip_topic = format!("{}/internal/roundtrip", base_topic);
|
let round_trip_topic = format!("{}/internal/roundtrip", base_topic);
|
||||||
let stay_alive_topic = format!("{}/stay_alive", base_topic);
|
let stay_alive_topic = format!("{}/stay_alive", base_topic);
|
||||||
println!("Stay alive topic is {}", stay_alive_topic);
|
log(LogMessage::stay_alive, 0 ,0,"", &stay_alive_topic);
|
||||||
|
|
||||||
let mqtt_connected_event_received_copy = mqtt_connected_event_received.clone();
|
let mqtt_connected_event_received_copy = mqtt_connected_event_received.clone();
|
||||||
let mqtt_connected_event_ok_copy = mqtt_connected_event_ok.clone();
|
let mqtt_connected_event_ok_copy = mqtt_connected_event_ok.clone();
|
||||||
let stay_alive_topic_copy = stay_alive_topic.clone();
|
let stay_alive_topic_copy = stay_alive_topic.clone();
|
||||||
let round_trip_topic_copy = round_trip_topic.clone();
|
let round_trip_topic_copy = round_trip_topic.clone();
|
||||||
let round_trip_ok_copy = round_trip_ok.clone();
|
let round_trip_ok_copy = round_trip_ok.clone();
|
||||||
println!(
|
let client_id = mqtt_client_config.client_id.unwrap_or("not set");
|
||||||
"Connecting mqtt {} with id {}",
|
log(LogMessage::mqtt_info, 0 ,0,client_id, &mqtt_url);
|
||||||
mqtt_url,
|
|
||||||
mqtt_client_config.client_id.unwrap_or("not set")
|
|
||||||
);
|
|
||||||
let mut client = EspMqttClient::new_cb(&mqtt_url, &mqtt_client_config, move |event| {
|
let mut client = EspMqttClient::new_cb(&mqtt_url, &mqtt_client_config, move |event| {
|
||||||
let payload = event.payload();
|
let payload = event.payload();
|
||||||
match payload {
|
match payload {
|
||||||
@ -987,10 +965,10 @@ impl PlantCtrlBoard<'_> {
|
|||||||
} else if topic.eq(stay_alive_topic_copy.as_str()) {
|
} else if topic.eq(stay_alive_topic_copy.as_str()) {
|
||||||
let value =
|
let value =
|
||||||
data.eq_ignore_ascii_case("true") || data.eq_ignore_ascii_case("1");
|
data.eq_ignore_ascii_case("true") || data.eq_ignore_ascii_case("1");
|
||||||
println!("Received stay alive with value {}", value);
|
log(LogMessage::mqtt_stay_alive_rec, 0 ,0,&data, "");
|
||||||
STAY_ALIVE.store(value, std::sync::atomic::Ordering::Relaxed);
|
STAY_ALIVE.store(value, std::sync::atomic::Ordering::Relaxed);
|
||||||
} else {
|
} else {
|
||||||
println!("Unknown topic recieved {}", topic);
|
log(LogMessage::unknown_topic, 0 ,0,"", &topic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1327,6 +1305,38 @@ impl PlantHal {
|
|||||||
pub fn create() -> Result<Mutex<PlantCtrlBoard<'static>>> {
|
pub fn create() -> Result<Mutex<PlantCtrlBoard<'static>>> {
|
||||||
let peripherals = Peripherals::take()?;
|
let peripherals = Peripherals::take()?;
|
||||||
|
|
||||||
|
let mut clock = PinDriver::input_output(peripherals.pins.gpio15.downgrade())?;
|
||||||
|
clock.set_pull(Pull::Floating).unwrap();
|
||||||
|
let mut latch = PinDriver::input_output(peripherals.pins.gpio3.downgrade())?;
|
||||||
|
latch.set_pull(Pull::Floating).unwrap();
|
||||||
|
let mut data = PinDriver::input_output(peripherals.pins.gpio23.downgrade())?;
|
||||||
|
data.set_pull(Pull::Floating).unwrap();
|
||||||
|
let shift_register = ShiftRegister40::new(clock.into(), latch.into(), data.into());
|
||||||
|
//disable all
|
||||||
|
for mut pin in shift_register.decompose() {
|
||||||
|
pin.set_low().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let awake = &mut shift_register.decompose()[AWAKE];
|
||||||
|
awake.set_high()?;
|
||||||
|
|
||||||
|
|
||||||
|
let charging = &mut shift_register.decompose()[CHARGING];
|
||||||
|
charging.set_high()?;
|
||||||
|
|
||||||
|
let ms0 = &mut shift_register.decompose()[MS_0];
|
||||||
|
ms0.set_low()?;
|
||||||
|
let ms1 = &mut shift_register.decompose()[MS_1];
|
||||||
|
ms1.set_low()?;
|
||||||
|
let ms2 = &mut shift_register.decompose()[MS_2];
|
||||||
|
ms2.set_low()?;
|
||||||
|
let ms3 = &mut shift_register.decompose()[MS_3];
|
||||||
|
ms3.set_low()?;
|
||||||
|
|
||||||
|
let ms4 = &mut shift_register.decompose()[MS_4];
|
||||||
|
ms4.set_high()?;
|
||||||
|
|
||||||
|
|
||||||
println!("Init battery driver");
|
println!("Init battery driver");
|
||||||
let mut battery_driver = Bq34z100g1Driver {
|
let mut battery_driver = Bq34z100g1Driver {
|
||||||
i2c: MutexDevice::new(&I2C_DRIVER),
|
i2c: MutexDevice::new(&I2C_DRIVER),
|
||||||
@ -1345,6 +1355,10 @@ impl PlantHal {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut one_wire_pin = PinDriver::input_output_od(peripherals.pins.gpio18)?;
|
||||||
|
one_wire_pin.set_pull(Pull::Floating).unwrap();
|
||||||
|
|
||||||
|
|
||||||
let rtc_time = rtc.datetime();
|
let rtc_time = rtc.datetime();
|
||||||
match rtc_time {
|
match rtc_time {
|
||||||
OkStd(tt) => {
|
OkStd(tt) => {
|
||||||
@ -1363,33 +1377,6 @@ impl PlantHal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut clock = PinDriver::input_output(peripherals.pins.gpio15.downgrade())?;
|
|
||||||
clock.set_pull(Pull::Floating).unwrap();
|
|
||||||
let mut latch = PinDriver::input_output(peripherals.pins.gpio3.downgrade())?;
|
|
||||||
latch.set_pull(Pull::Floating).unwrap();
|
|
||||||
let mut data = PinDriver::input_output(peripherals.pins.gpio23.downgrade())?;
|
|
||||||
data.set_pull(Pull::Floating).unwrap();
|
|
||||||
let shift_register = ShiftRegister40::new(clock.into(), latch.into(), data.into());
|
|
||||||
for mut pin in shift_register.decompose() {
|
|
||||||
pin.set_low().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut one_wire_pin = PinDriver::input_output_od(peripherals.pins.gpio18)?;
|
|
||||||
one_wire_pin.set_pull(Pull::Floating).unwrap();
|
|
||||||
|
|
||||||
//disable all
|
|
||||||
let ms0 = &mut shift_register.decompose()[MS_0];
|
|
||||||
ms0.set_low()?;
|
|
||||||
let ms1 = &mut shift_register.decompose()[MS_1];
|
|
||||||
ms1.set_low()?;
|
|
||||||
let ms2 = &mut shift_register.decompose()[MS_2];
|
|
||||||
ms2.set_low()?;
|
|
||||||
let ms3 = &mut shift_register.decompose()[MS_3];
|
|
||||||
ms3.set_low()?;
|
|
||||||
|
|
||||||
let ms4 = &mut shift_register.decompose()[MS_4];
|
|
||||||
ms4.set_high()?;
|
|
||||||
|
|
||||||
//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;
|
||||||
@ -1430,13 +1417,13 @@ impl PlantHal {
|
|||||||
init_rtc_store = true
|
init_rtc_store = true
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
println!("Reset due to {:?} requires rtc clear {} and force config mode {}", reasons, init_rtc_store, to_config_mode);
|
log(LogMessage::reset_reason, init_rtc_store as u32, to_config_mode as u32, "",&format!("{reasons:?}"));
|
||||||
if init_rtc_store {
|
if init_rtc_store {
|
||||||
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 = false;
|
||||||
BUFFER = ConstGenericRingBuffer::<heapless::String<ENTRY_SIZE>, BUFFER_SIZE>::new();
|
crate::log::init();
|
||||||
RESTART_TO_CONF = to_config_mode;
|
RESTART_TO_CONF = to_config_mode;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@ -1444,12 +1431,8 @@ impl PlantHal {
|
|||||||
if to_config_mode{
|
if to_config_mode{
|
||||||
RESTART_TO_CONF = true;
|
RESTART_TO_CONF = true;
|
||||||
}
|
}
|
||||||
println!("Current restart to conf mode{:?}", RESTART_TO_CONF);
|
log(LogMessage::restart_to_config, RESTART_TO_CONF as u32, 0, "","");
|
||||||
|
log(LogMessage::low_voltage, LOW_VOLTAGE_DETECTED as u32, 0, "","");
|
||||||
println!(
|
|
||||||
"Current low voltage detection is {:?}",
|
|
||||||
LOW_VOLTAGE_DETECTED
|
|
||||||
);
|
|
||||||
for i in 0..PLANT_COUNT {
|
for i in 0..PLANT_COUNT {
|
||||||
println!(
|
println!(
|
||||||
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
|
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
|
||||||
@ -1473,8 +1456,6 @@ impl PlantHal {
|
|||||||
Option::<AnyInputPin>::None,
|
Option::<AnyInputPin>::None,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
println!("Channel config start");
|
|
||||||
|
|
||||||
counter_unit1.channel_config(
|
counter_unit1.channel_config(
|
||||||
PcntChannel::Channel0,
|
PcntChannel::Channel0,
|
||||||
PinIndex::Pin0,
|
PinIndex::Pin0,
|
||||||
@ -1489,8 +1470,6 @@ impl PlantHal {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
println!("Wifi start");
|
|
||||||
|
|
||||||
let sys_loop = EspSystemEventLoop::take()?;
|
let sys_loop = EspSystemEventLoop::take()?;
|
||||||
let nvs = EspDefaultNvsPartition::take()?;
|
let nvs = EspDefaultNvsPartition::take()?;
|
||||||
let wifi_driver = EspWifi::new(peripherals.modem, sys_loop, Some(nvs))?;
|
let wifi_driver = EspWifi::new(peripherals.modem, sys_loop, Some(nvs))?;
|
||||||
@ -1525,15 +1504,15 @@ impl PlantHal {
|
|||||||
let one_wire_bus = OneWire::new(one_wire_pin)
|
let one_wire_bus = OneWire::new(one_wire_pin)
|
||||||
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
||||||
|
|
||||||
println!("After stuff");
|
|
||||||
|
|
||||||
let status = print_battery(&mut battery_driver);
|
let status = print_battery(&mut battery_driver);
|
||||||
if status.is_err() {
|
match status {
|
||||||
println!("Error communicating with battery!! {:?}", status.err());
|
OkStd(_) => {
|
||||||
} else {
|
|
||||||
println!("Managed to comunnicate with battery");
|
},
|
||||||
|
Err(err) => {
|
||||||
|
log(LogMessage::battery_communication_error, 0 as u32, 0, "",&format!("{err:?})"));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let shift_register_enable_invert = PinDriver::output(peripherals.pins.gpio21.downgrade())?;
|
let shift_register_enable_invert = PinDriver::output(peripherals.pins.gpio21.downgrade())?;
|
||||||
|
|
||||||
let rv = Mutex::new(PlantCtrlBoard {
|
let rv = Mutex::new(PlantCtrlBoard {
|
||||||
|
@ -9,6 +9,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
|
use esp_idf_sys::{esp_set_time_from_rtc, settimeofday, timeval, vTaskDelay};
|
||||||
use core::result::Result::Ok;
|
use core::result::Result::Ok;
|
||||||
use embedded_svc::http::Method;
|
use embedded_svc::http::Method;
|
||||||
use esp_idf_hal::delay::Delay;
|
use esp_idf_hal::delay::Delay;
|
||||||
@ -24,11 +25,6 @@ struct SSIDList<'a> {
|
|||||||
ssids: Vec<&'a String<32>>,
|
ssids: Vec<&'a String<32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
|
||||||
struct FileList {
|
|
||||||
file: Vec<FileInfo>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
struct LoadData<'a> {
|
struct LoadData<'a> {
|
||||||
rtc: &'a str,
|
rtc: &'a str,
|
||||||
@ -64,6 +60,12 @@ fn write_time(
|
|||||||
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).map_err(|err| anyhow::anyhow!(err))?;
|
let parsed = DateTime::parse_from_rfc3339(time.time).map_err(|err| anyhow::anyhow!(err))?;
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
|
|
||||||
|
let now = timeval {
|
||||||
|
tv_sec: parsed.to_utc().timestamp(),
|
||||||
|
tv_usec: 0
|
||||||
|
};
|
||||||
|
unsafe { settimeofday(&now, core::ptr::null_mut()) };
|
||||||
board.set_rtc_time(&parsed.to_utc())?;
|
board.set_rtc_time(&parsed.to_utc())?;
|
||||||
anyhow::Ok(None)
|
anyhow::Ok(None)
|
||||||
}
|
}
|
||||||
@ -440,6 +442,8 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
unsafe { vTaskDelay(1) };
|
||||||
|
|
||||||
let reboot_now_for_exit = reboot_now.clone();
|
let reboot_now_for_exit = reboot_now.clone();
|
||||||
server
|
server
|
||||||
.fn_handler("/exit", Method::Post, move |_| {
|
.fn_handler("/exit", Method::Post, move |_| {
|
||||||
@ -462,19 +466,16 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
||||||
let mut total_read: usize = 0;
|
let mut total_read: usize = 0;
|
||||||
loop {
|
loop {
|
||||||
|
unsafe { vTaskDelay(1) };
|
||||||
let read = std::io::Read::read(&mut file_handle, &mut buffer)?;
|
let read = std::io::Read::read(&mut file_handle, &mut buffer)?;
|
||||||
total_read += read;
|
total_read += read;
|
||||||
println!(
|
|
||||||
"sending {read} bytes of {total_read} for file {}",
|
|
||||||
&filename
|
|
||||||
);
|
|
||||||
let to_write = &buffer[0..read];
|
let to_write = &buffer[0..read];
|
||||||
response.write(to_write)?;
|
response.write(to_write)?;
|
||||||
println!("wrote {read} bytes of {total_read} for file {filename}");
|
|
||||||
if read == 0 {
|
if read == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println!("wrote {total_read} for file {filename}");
|
||||||
drop(file_handle);
|
drop(file_handle);
|
||||||
response.flush()?;
|
response.flush()?;
|
||||||
}
|
}
|
||||||
@ -588,6 +589,7 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
unsafe { vTaskDelay(1) };
|
||||||
server
|
server
|
||||||
.fn_handler("/", Method::Get, move |request| {
|
.fn_handler("/", Method::Get, move |request| {
|
||||||
let mut response = request.into_ok_response()?;
|
let mut response = request.into_ok_response()?;
|
||||||
|
74
website/.github/workflows/pages.yml
vendored
Normal file
74
website/.github/workflows/pages.yml
vendored
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# Sample workflow for building and deploying a Hugo site to GitHub Pages
|
||||||
|
name: Blowfish Docs Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
# Runs on pushes targeting the default branch
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
|
||||||
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
# Allow one concurrent deployment
|
||||||
|
concurrency:
|
||||||
|
group: "pages"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
# Default to bash
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Build job
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Hugo setup
|
||||||
|
uses: peaceiris/actions-hugo@v2.6.0
|
||||||
|
with:
|
||||||
|
hugo-version: 0.140.2
|
||||||
|
extended: true
|
||||||
|
env:
|
||||||
|
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
|
||||||
|
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true # Fetch Hugo themes (true OR recursive)
|
||||||
|
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
|
||||||
|
|
||||||
|
- name: Setup Pages
|
||||||
|
id: pages
|
||||||
|
uses: actions/configure-pages@v2
|
||||||
|
|
||||||
|
- name: Build with Hugo
|
||||||
|
env:
|
||||||
|
# For maximum backward compatibility with Hugo modules
|
||||||
|
HUGO_ENVIRONMENT: production
|
||||||
|
HUGO_ENV: production
|
||||||
|
run: |
|
||||||
|
hugo --minify -d ./public --baseURL https://nunocoracao.github.io/blowfish_template/
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v1
|
||||||
|
with:
|
||||||
|
path: ./public
|
||||||
|
|
||||||
|
# Deployment job
|
||||||
|
deploy:
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: https://nunocoracao.github.io/blowfish_template/
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v1
|
4
website/.gitmodules
vendored
Normal file
4
website/.gitmodules
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[submodule "themes/blowfish"]
|
||||||
|
path = themes/blowfish
|
||||||
|
url = https://github.com/nunocoracao/blowfish.git
|
||||||
|
branch = main
|
21
website/LICENSE
Normal file
21
website/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Nuno Coração
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
6
website/README.md
Normal file
6
website/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Blowfish Template
|
||||||
|
This is a template for the Blowfish Hugo Theme. Feel free to use this repo as a quick way to get started with Blowfish. Please visit [Blowfish's main website](https://github.com/nunocoracao/blowfish) to read the complete documentation.
|
||||||
|
|
||||||
|
The template was built using the [Git option](https://nunocoracao.github.io/blowfish/docs/installation/#install-using-git) from Blowfish's installations instructions.
|
||||||
|
|
||||||
|

|
BIN
website/logo.png
Normal file
BIN
website/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
20
website/package.json
Normal file
20
website/package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "blowfish_template",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Blowfish Template",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "hugo server --minify -D -E -F"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/nunocoracao/blowfish_template.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/nunocoracao/blowfish_template/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/nunocoracao/blowfish_template#readme"
|
||||||
|
}
|
5
website/update.sh
Normal file
5
website/update.sh
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
git submodule update --remote --merge
|
||||||
|
git add *
|
||||||
|
git commit -m "updated theme"
|
||||||
|
git push
|
Loading…
x
Reference in New Issue
Block a user