initial webserver stub running
This commit is contained in:
parent
be3c4a5095
commit
b3cc313139
@ -1,16 +1,16 @@
|
|||||||
[build]
|
[build]
|
||||||
rustflags = [
|
rustflags = [
|
||||||
# Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.)
|
# Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.)
|
||||||
# NOTE: May negatively impact performance of produced code
|
# NOTE: May negatively impact performance of produced code
|
||||||
"-C", "force-frame-pointers",
|
"-C", "force-frame-pointers",
|
||||||
"-Z", "stack-protector=all",
|
"-Z", "stack-protector=all",
|
||||||
"-C", "link-arg=-Tlinkall.x",
|
"-C", "link-arg=-Tlinkall.x",
|
||||||
]
|
]
|
||||||
|
|
||||||
target = "riscv32imac-unknown-none-elf"
|
target = "riscv32imac-unknown-none-elf"
|
||||||
|
|
||||||
[target.riscv32imac-unknown-none-elf]
|
[target.riscv32imac-unknown-none-elf]
|
||||||
runner = "espflash flash --monitor --chip esp32c6"
|
runner = "espflash flash --monitor --chip esp32c6 --baud 921600 --partition-table partitions.csv"
|
||||||
#runner = "espflash flash --monitor --baud 921600 --partition-table partitions.csv -b no-reset" # Select this runner in case of usb ttl
|
#runner = "espflash flash --monitor --baud 921600 --partition-table partitions.csv -b no-reset" # Select this runner in case of usb ttl
|
||||||
#runner = "espflash flash --monitor"
|
#runner = "espflash flash --monitor"
|
||||||
#runner = "cargo runner"
|
#runner = "cargo runner"
|
||||||
@ -22,7 +22,7 @@ runner = "espflash flash --monitor --chip esp32c6"
|
|||||||
[env]
|
[env]
|
||||||
CHRONO_TZ_TIMEZONE_FILTER = "UTC|America/New_York|America/Chicago|America/Los_Angeles|Europe/London|Europe/Berlin|Europe/Paris|Asia/Tokyo|Asia/Shanghai|Asia/Kolkata|Australia/Sydney|America/Sao_Paulo|Africa/Johannesburg|Asia/Dubai|Pacific/Auckland"
|
CHRONO_TZ_TIMEZONE_FILTER = "UTC|America/New_York|America/Chicago|America/Los_Angeles|Europe/London|Europe/Berlin|Europe/Paris|Asia/Tokyo|Asia/Shanghai|Asia/Kolkata|Australia/Sydney|America/Sao_Paulo|Africa/Johannesburg|Asia/Dubai|Pacific/Auckland"
|
||||||
CARGO_WORKSPACE_DIR = { value = "", relative = true }
|
CARGO_WORKSPACE_DIR = { value = "", relative = true }
|
||||||
ESP_LOG="info"
|
ESP_LOG = "info"
|
||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
build-std = ["alloc", "core"]
|
build-std = ["alloc", "core"]
|
||||||
|
@ -155,6 +155,7 @@ edge-dhcp = "0.6.0"
|
|||||||
edge-nal = "0.5.0"
|
edge-nal = "0.5.0"
|
||||||
edge-nal-embassy = "0.6.0"
|
edge-nal-embassy = "0.6.0"
|
||||||
static_cell = "2.1.1"
|
static_cell = "2.1.1"
|
||||||
|
cfg-if = "1.0.3"
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
partition_table = "partitions.csv"
|
format = "EspIdf"
|
||||||
[connection]
|
|
||||||
serial = "/dev/ttyACM0"
|
[idf_format_args]
|
||||||
|
|
||||||
[flash]
|
[flash]
|
||||||
size = "16MB"
|
size = "16MB"
|
@ -1,5 +1,5 @@
|
|||||||
use crate::config::{NetworkConfig, PlantControllerConfig};
|
use crate::config::{NetworkConfig, PlantControllerConfig};
|
||||||
use crate::hal::PLANT_COUNT;
|
use crate::hal::{GW_IP_ADDR_ENV, PLANT_COUNT};
|
||||||
use crate::log::{log, LogMessage};
|
use crate::log::{log, LogMessage};
|
||||||
use crate::STAY_ALIVE;
|
use crate::STAY_ALIVE;
|
||||||
use anyhow::{anyhow, bail, Context};
|
use anyhow::{anyhow, bail, Context};
|
||||||
@ -8,12 +8,21 @@ use serde::Serialize;
|
|||||||
|
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::net::IpAddr;
|
use core::net::{IpAddr, Ipv4Addr};
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use embassy_time::Instant;
|
use embassy_executor::{SendSpawner, Spawner};
|
||||||
|
use embassy_net::tcp::TcpSocket;
|
||||||
|
use embassy_net::{IpListenEndpoint, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||||
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
use esp_bootloader_esp_idf::ota::OtaImageState;
|
use esp_bootloader_esp_idf::ota::OtaImageState;
|
||||||
use esp_hal::gpio::Input;
|
use esp_hal::gpio::Input;
|
||||||
|
use esp_hal::rng::Rng;
|
||||||
|
use esp_println::{print, println};
|
||||||
use esp_storage::FlashStorage;
|
use esp_storage::FlashStorage;
|
||||||
|
use esp_wifi::wifi::{
|
||||||
|
AccessPointConfiguration, Configuration, Interfaces, WifiController, WifiDevice, WifiEvent,
|
||||||
|
WifiState,
|
||||||
|
};
|
||||||
|
|
||||||
#[link_section = ".rtc.data"]
|
#[link_section = ".rtc.data"]
|
||||||
static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT];
|
static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT];
|
||||||
@ -51,12 +60,17 @@ pub struct MqttClient<'a> {
|
|||||||
base_topic: heapless::String<64>,
|
base_topic: heapless::String<64>,
|
||||||
}
|
}
|
||||||
pub struct Esp<'a> {
|
pub struct Esp<'a> {
|
||||||
pub boot_button: Input<'a>,
|
pub rng: Rng,
|
||||||
|
//first starter (ap or sta will take these)
|
||||||
|
pub interfaces: Option<Interfaces<'static>>,
|
||||||
|
pub controller: Option<WifiController<'static>>,
|
||||||
|
|
||||||
|
//only filled, if a useable mqtt client with working roundtrip could be established
|
||||||
pub(crate) mqtt_client: Option<MqttClient<'a>>,
|
pub(crate) mqtt_client: Option<MqttClient<'a>>,
|
||||||
pub(crate) dummy: PhantomData<&'a ()>,
|
|
||||||
|
pub boot_button: Input<'a>,
|
||||||
pub(crate) wall_clock_offset: u64,
|
pub(crate) wall_clock_offset: u64,
|
||||||
//pub(crate) wifi_driver: EspWifi<'a>,
|
|
||||||
//pub(crate) boot_button: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
|
|
||||||
pub storage: FlashStorage,
|
pub storage: FlashStorage,
|
||||||
pub slot: usize,
|
pub slot: usize,
|
||||||
pub next_slot: usize,
|
pub next_slot: usize,
|
||||||
@ -71,6 +85,17 @@ pub struct IpInfo {
|
|||||||
|
|
||||||
struct AccessPointInfo {}
|
struct AccessPointInfo {}
|
||||||
|
|
||||||
|
macro_rules! mk_static {
|
||||||
|
($t:ty,$val:expr) => {{
|
||||||
|
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
||||||
|
#[deny(unused_attributes)]
|
||||||
|
let x = STATIC_CELL.uninit().write(($val));
|
||||||
|
x
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
static WIFI_CONTROLLER: static_cell::StaticCell<WifiController> = static_cell::StaticCell::new();
|
||||||
|
|
||||||
impl Esp<'_> {
|
impl Esp<'_> {
|
||||||
const SPIFFS_PARTITION_NAME: &'static str = "storage";
|
const SPIFFS_PARTITION_NAME: &'static str = "storage";
|
||||||
const CONFIG_FILE: &'static str = "/spiffs/config.cfg";
|
const CONFIG_FILE: &'static str = "/spiffs/config.cfg";
|
||||||
@ -150,24 +175,58 @@ impl Esp<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn wifi_ap(&mut self) -> anyhow::Result<()> {
|
pub(crate) async fn wifi_ap(&mut self) -> anyhow::Result<Stack> {
|
||||||
let _ssid = match self.load_config() {
|
let _ssid = match self.load_config() {
|
||||||
Ok(config) => config.network.ap_ssid.clone(),
|
Ok(config) => config.network.ap_ssid.clone(),
|
||||||
Err(_) => heapless::String::from_str("PlantCtrl Emergency Mode").unwrap(),
|
Err(_) => heapless::String::from_str("PlantCtrl Emergency Mode").unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
todo!("todo");
|
let spawner = Spawner::for_current_executor().await;
|
||||||
//
|
|
||||||
// let apconfig = AccessPointConfiguration {
|
let device = self.interfaces.take().unwrap().ap;
|
||||||
// ssid,
|
let gw_ip_addr_str = GW_IP_ADDR_ENV.unwrap_or("192.168.2.1");
|
||||||
// auth_method: AuthMethod::None,
|
let gw_ip_addr = Ipv4Addr::from_str(gw_ip_addr_str).expect("failed to parse gateway ip");
|
||||||
// ssid_hidden: false,
|
|
||||||
// ..Default::default()
|
let config = embassy_net::Config::ipv4_static(StaticConfigV4 {
|
||||||
// };
|
address: Ipv4Cidr::new(gw_ip_addr, 24),
|
||||||
// self.wifi_driver
|
gateway: Some(gw_ip_addr),
|
||||||
// .set_configuration(&Configuration::AccessPoint(apconfig))?;
|
dns_servers: Default::default(),
|
||||||
// self.wifi_driver.start()?;
|
});
|
||||||
// anyhow::Ok(())
|
|
||||||
|
let seed = (self.rng.random() as u64) << 32 | self.rng.random() as u64;
|
||||||
|
|
||||||
|
// Init network stack
|
||||||
|
let (stack, runner) = embassy_net::new(
|
||||||
|
device,
|
||||||
|
config,
|
||||||
|
mk_static!(StackResources<3>, StackResources::<3>::new()),
|
||||||
|
seed,
|
||||||
|
);
|
||||||
|
let stack = mk_static!(Stack, stack);
|
||||||
|
|
||||||
|
let controller = self.controller.take().unwrap();
|
||||||
|
spawner.spawn(connection(controller)).ok();
|
||||||
|
spawner.spawn(net_task(runner)).ok();
|
||||||
|
spawner.spawn(run_dhcp(stack, gw_ip_addr_str)).ok();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if stack.is_link_up() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"Connect to the AP `esp-wifi` and point your browser to http://{gw_ip_addr_str}:8080/"
|
||||||
|
);
|
||||||
|
println!("DHCP is enabled so there's no need to configure a static IP, just in case:");
|
||||||
|
while !stack.is_config_up() {
|
||||||
|
Timer::after(Duration::from_millis(100)).await
|
||||||
|
}
|
||||||
|
stack
|
||||||
|
.config_v4()
|
||||||
|
.inspect(|c| println!("ipv4 config: {c:?}"));
|
||||||
|
|
||||||
|
anyhow::Ok(stack.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> anyhow::Result<IpInfo> {
|
pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> anyhow::Result<IpInfo> {
|
||||||
@ -638,3 +697,74 @@ impl Esp<'_> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn run_dhcp(stack: &'static Stack<'static>, gw_ip_addr: &'static str) {
|
||||||
|
use core::net::{Ipv4Addr, SocketAddrV4};
|
||||||
|
|
||||||
|
use edge_dhcp::{
|
||||||
|
io::{self, DEFAULT_SERVER_PORT},
|
||||||
|
server::{Server, ServerOptions},
|
||||||
|
};
|
||||||
|
use edge_nal::UdpBind;
|
||||||
|
use edge_nal_embassy::{Udp, UdpBuffers};
|
||||||
|
|
||||||
|
let ip = Ipv4Addr::from_str(gw_ip_addr).expect("dhcp task failed to parse gw ip");
|
||||||
|
|
||||||
|
let mut buf = [0u8; 1500];
|
||||||
|
|
||||||
|
let mut gw_buf = [Ipv4Addr::UNSPECIFIED];
|
||||||
|
|
||||||
|
let buffers = UdpBuffers::<3, 1024, 1024, 10>::new();
|
||||||
|
let unbound_socket = Udp::new(*stack, &buffers);
|
||||||
|
let mut bound_socket = unbound_socket
|
||||||
|
.bind(core::net::SocketAddr::V4(SocketAddrV4::new(
|
||||||
|
Ipv4Addr::UNSPECIFIED,
|
||||||
|
DEFAULT_SERVER_PORT,
|
||||||
|
)))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
_ = io::server::run(
|
||||||
|
&mut Server::<_, 64>::new_with_et(ip),
|
||||||
|
&ServerOptions::new(ip, Some(&mut gw_buf)),
|
||||||
|
&mut bound_socket,
|
||||||
|
&mut buf,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.inspect_err(|e| log::warn!("DHCP server error: {e:?}"));
|
||||||
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn connection(mut controller: WifiController<'static>) {
|
||||||
|
println!("start connection task");
|
||||||
|
println!("Device capabilities: {:?}", controller.capabilities());
|
||||||
|
loop {
|
||||||
|
match esp_wifi::wifi::wifi_state() {
|
||||||
|
WifiState::ApStarted => {
|
||||||
|
// wait until we're no longer connected
|
||||||
|
controller.wait_for_event(WifiEvent::ApStop).await;
|
||||||
|
Timer::after(Duration::from_millis(5000)).await
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
if !matches!(controller.is_started(), core::result::Result::Ok(true)) {
|
||||||
|
let client_config = Configuration::AccessPoint(AccessPointConfiguration {
|
||||||
|
ssid: "esp-wifi".try_into().unwrap(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
controller.set_configuration(&client_config).unwrap();
|
||||||
|
println!("Starting wifi");
|
||||||
|
controller.start_async().await.unwrap();
|
||||||
|
println!("Wifi started!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) {
|
||||||
|
runner.run().await
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
pub(crate) mod battery;
|
pub(crate) mod battery;
|
||||||
mod esp;
|
pub mod esp;
|
||||||
mod initial_hal;
|
mod initial_hal;
|
||||||
mod rtc;
|
mod rtc;
|
||||||
//mod water;
|
//mod water;
|
||||||
@ -19,21 +19,34 @@ use alloc::boxed::Box;
|
|||||||
use alloc::format;
|
use alloc::format;
|
||||||
use anyhow::{Ok, Result};
|
use anyhow::{Ok, Result};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use core::cell::OnceCell;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use embassy_executor::Spawner;
|
use core::net::Ipv4Addr;
|
||||||
|
use core::str::FromStr;
|
||||||
|
use embassy_executor::{SendSpawner, Spawner};
|
||||||
|
use embassy_net::tcp::{Error, TcpSocket};
|
||||||
|
use embassy_net::{IpListenEndpoint, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
|
||||||
//use battery::BQ34Z100G1;
|
//use battery::BQ34Z100G1;
|
||||||
//use bq34z100::Bq34z100g1Driver;
|
//use bq34z100::Bq34z100g1Driver;
|
||||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::once_lock::OnceLock;
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
use esp_bootloader_esp_idf::partitions::DataPartitionSubType;
|
use esp_bootloader_esp_idf::partitions::DataPartitionSubType;
|
||||||
use esp_hal::clock::CpuClock;
|
use esp_hal::clock::CpuClock;
|
||||||
use esp_hal::gpio::{Input, InputConfig, Pull};
|
use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||||
use esp_hal::timer::systimer::SystemTimer;
|
use esp_hal::timer::systimer::SystemTimer;
|
||||||
use esp_println::println;
|
use esp_println::{print, println};
|
||||||
use measurements::{Current, Voltage};
|
use measurements::{Current, Voltage};
|
||||||
|
|
||||||
|
use embassy_sync::mutex::{Mutex, MutexGuard};
|
||||||
use esp_alloc as _;
|
use esp_alloc as _;
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
use esp_hal::rng::Rng;
|
||||||
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
|
use esp_wifi::wifi::{
|
||||||
|
AccessPointConfiguration, Configuration, WifiController, WifiDevice, WifiEvent, WifiState,
|
||||||
|
};
|
||||||
|
use esp_wifi::{init, EspWifiController};
|
||||||
|
|
||||||
//Only support for 8 right now!
|
//Only support for 8 right now!
|
||||||
pub const PLANT_COUNT: usize = 8;
|
pub const PLANT_COUNT: usize = 8;
|
||||||
@ -42,16 +55,6 @@ const TANK_MULTI_SAMPLE: usize = 11;
|
|||||||
|
|
||||||
//pub static I2C_DRIVER: LazyLock<Mutex<CriticalSectionRawMutex,I2cDriver<'static>>> = LazyLock::new(PlantHal::create_i2c);
|
//pub static I2C_DRIVER: LazyLock<Mutex<CriticalSectionRawMutex,I2cDriver<'static>>> = LazyLock::new(PlantHal::create_i2c);
|
||||||
|
|
||||||
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
|
|
||||||
macro_rules! mk_static {
|
|
||||||
($t:ty,$val:expr) => {{
|
|
||||||
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
|
||||||
#[deny(unused_attributes)]
|
|
||||||
let x = STATIC_CELL.uninit().write(($val));
|
|
||||||
x
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deep_sleep(_duration_in_ms: u64) -> ! {
|
fn deep_sleep(_duration_in_ms: u64) -> ! {
|
||||||
//unsafe {
|
//unsafe {
|
||||||
// //if we don't do this here, we might just revert newly flashed firmware
|
// //if we don't do this here, we might just revert newly flashed firmware
|
||||||
@ -159,6 +162,17 @@ pub struct FreePeripherals {
|
|||||||
// pub can: CAN,
|
// pub can: CAN,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! mk_static {
|
||||||
|
($t:ty,$val:expr) => {{
|
||||||
|
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
||||||
|
#[deny(unused_attributes)]
|
||||||
|
let x = STATIC_CELL.uninit().write(($val));
|
||||||
|
x
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
const GW_IP_ADDR_ENV: Option<&'static str> = option_env!("GATEWAY_IP");
|
||||||
|
|
||||||
impl PlantHal {
|
impl PlantHal {
|
||||||
// fn create_i2c() -> Mutex<CriticalSectionRawMutex, I2cDriver<'static>> {
|
// fn create_i2c() -> Mutex<CriticalSectionRawMutex, I2cDriver<'static>> {
|
||||||
// let peripherals = unsafe { Peripherals::new() };
|
// let peripherals = unsafe { Peripherals::new() };
|
||||||
@ -176,19 +190,31 @@ impl PlantHal {
|
|||||||
// Mutex::new(I2cDriver::new(i2c, sda, scl, &config).unwrap())
|
// Mutex::new(I2cDriver::new(i2c, sda, scl, &config).unwrap())
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn create(spawner: Spawner) -> Result<Mutex<CriticalSectionRawMutex, HAL<'static>>> {
|
pub async fn create(spawner: Spawner) -> Result<Mutex<CriticalSectionRawMutex, HAL<'static>>> {
|
||||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||||
let peripherals = esp_hal::init(config);
|
let peripherals = esp_hal::init(config);
|
||||||
|
|
||||||
esp_alloc::heap_allocator!(size: 64 * 1024);
|
esp_alloc::heap_allocator!(size: 64 * 1024);
|
||||||
let systimer = SystemTimer::new(peripherals.SYSTIMER);
|
let systimer = SystemTimer::new(peripherals.SYSTIMER);
|
||||||
esp_hal_embassy::init(systimer.alarm0);
|
|
||||||
|
|
||||||
let boot_button = Input::new(
|
let boot_button = Input::new(
|
||||||
peripherals.GPIO9,
|
peripherals.GPIO9,
|
||||||
InputConfig::default().with_pull(Pull::None),
|
InputConfig::default().with_pull(Pull::None),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut rng = Rng::new(peripherals.RNG);
|
||||||
|
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
||||||
|
let esp_wifi_ctrl = &*mk_static!(
|
||||||
|
EspWifiController<'static>,
|
||||||
|
init(timg0.timer0, rng.clone()).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let (mut controller, interfaces) =
|
||||||
|
esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap();
|
||||||
|
|
||||||
|
use esp_hal::timer::systimer::SystemTimer;
|
||||||
|
esp_hal_embassy::init(systimer.alarm0);
|
||||||
|
|
||||||
//
|
//
|
||||||
// let free_pins = FreePeripherals {
|
// let free_pins = FreePeripherals {
|
||||||
// can: peripherals.can,
|
// can: peripherals.can,
|
||||||
@ -255,15 +281,16 @@ impl PlantHal {
|
|||||||
let ota_state = ota.current_ota_state()?;
|
let ota_state = ota.current_ota_state()?;
|
||||||
|
|
||||||
let mut esp = Esp {
|
let mut esp = Esp {
|
||||||
|
rng,
|
||||||
|
controller: Some(controller),
|
||||||
|
interfaces: Some(interfaces),
|
||||||
boot_button,
|
boot_button,
|
||||||
mqtt_client: None,
|
mqtt_client: None,
|
||||||
storage,
|
storage,
|
||||||
slot: current.number(),
|
slot: current.number(),
|
||||||
next_slot: current.next().number(),
|
next_slot: current.next().number(),
|
||||||
ota_state,
|
ota_state,
|
||||||
dummy: PhantomData::default(),
|
wall_clock_offset: 0,
|
||||||
wall_clock_offset: 0, // wifi_driver,
|
|
||||||
// boot_button
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//init,reset rtc memory depending on cause
|
//init,reset rtc memory depending on cause
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
#![allow(dead_code)]
|
|
||||||
#![no_std]
|
|
||||||
extern crate embedded_hal as hal;
|
|
||||||
|
|
||||||
pub mod sipo;
|
|
@ -11,6 +11,7 @@ use esp_backtrace as _;
|
|||||||
|
|
||||||
use crate::config::PlantConfig;
|
use crate::config::PlantConfig;
|
||||||
use crate::tank::WATER_FROZEN_THRESH;
|
use crate::tank::WATER_FROZEN_THRESH;
|
||||||
|
use crate::webserver::httpd;
|
||||||
use crate::{
|
use crate::{
|
||||||
config::BoardVersion::INITIAL,
|
config::BoardVersion::INITIAL,
|
||||||
hal::{PlantHal, HAL, PLANT_COUNT},
|
hal::{PlantHal, HAL, PLANT_COUNT},
|
||||||
@ -23,7 +24,7 @@ use alloc::sync::Arc;
|
|||||||
use alloc::{format, vec};
|
use alloc::{format, vec};
|
||||||
use chrono::{DateTime, Datelike, Timelike, Utc};
|
use chrono::{DateTime, Datelike, Timelike, Utc};
|
||||||
use chrono_tz::Tz::{self};
|
use chrono_tz::Tz::{self};
|
||||||
use core::sync::atomic::Ordering;
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
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, MutexGuard};
|
||||||
@ -36,7 +37,6 @@ use esp_println::{logger, println};
|
|||||||
use hal::battery::BatteryState;
|
use hal::battery::BatteryState;
|
||||||
use log::{log, LogMessage};
|
use log::{log, LogMessage};
|
||||||
use plant_state::PlantState;
|
use plant_state::PlantState;
|
||||||
use portable_atomic::AtomicBool;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -57,7 +57,9 @@ mod config;
|
|||||||
mod hal;
|
mod hal;
|
||||||
mod log;
|
mod log;
|
||||||
mod plant_state;
|
mod plant_state;
|
||||||
|
mod sipo;
|
||||||
mod tank;
|
mod tank;
|
||||||
|
mod webserver;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
//mod webserver;
|
//mod webserver;
|
||||||
@ -235,11 +237,11 @@ async fn safe_main() -> anyhow::Result<()> {
|
|||||||
&& board.board_hal.get_config().network.ssid.is_none()
|
&& board.board_hal.get_config().network.ssid.is_none()
|
||||||
{
|
{
|
||||||
info!("No wifi configured, starting initial config mode");
|
info!("No wifi configured, starting initial config mode");
|
||||||
board.board_hal.get_esp().wifi_ap().await.unwrap();
|
let stack = board.board_hal.get_esp().wifi_ap().await?;
|
||||||
drop(board);
|
|
||||||
let reboot_now = Arc::new(AtomicBool::new(false));
|
let reboot_now = Arc::new(AtomicBool::new(false));
|
||||||
//TODO
|
println!("starting webserver");
|
||||||
//let _webserver = httpd(reboot_now.clone());
|
let _webserver = httpd(reboot_now.clone(), stack).await;
|
||||||
wait_infinity(WaitType::MissingConfig, reboot_now.clone()).await;
|
wait_infinity(WaitType::MissingConfig, reboot_now.clone()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,7 +1057,7 @@ async fn main(spawner: Spawner) {
|
|||||||
logger::init_logger_from_env();
|
logger::init_logger_from_env();
|
||||||
//force init here!
|
//force init here!
|
||||||
println!("Hal init");
|
println!("Hal init");
|
||||||
match BOARD_ACCESS.init(PlantHal::create(spawner).unwrap()) {
|
match BOARD_ACCESS.init(PlantHal::create(spawner).await.unwrap()) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
panic!("Could not set hal to static")
|
panic!("Could not set hal to static")
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
//! Serial-in parallel-out shift register
|
//! Serial-in parallel-out shift register
|
||||||
|
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
use core::mem::{self, MaybeUninit};
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::result::{Result, Result::Ok};
|
|
||||||
use core::iter::Iterator;
|
use core::iter::Iterator;
|
||||||
|
use core::mem::{self, MaybeUninit};
|
||||||
use hal::digital::OutputPin;
|
use core::result::{Result, Result::Ok};
|
||||||
|
use embedded_hal::digital::OutputPin;
|
||||||
|
|
||||||
trait ShiftRegisterInternal {
|
trait ShiftRegisterInternal {
|
||||||
fn update(&self, index: usize, command: bool) -> Result<(), ()>;
|
fn update(&self, index: usize, command: bool) -> Result<(), ()>;
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user