diff --git a/src/tasks/wifi.rs b/src/tasks/wifi.rs index deb874c..73f1cbe 100644 --- a/src/tasks/wifi.rs +++ b/src/tasks/wifi.rs @@ -1,6 +1,7 @@ -use alloc::string::{String, ToString}; +use alloc::string::ToString; use embassy_sync::channel::DynamicSender; use embassy_sync::pubsub::DynSubscriber; +use embassy_sync::watch::{DynReceiver, DynSender}; use embassy_time::{Duration, Instant, Timer, WithTimeout}; use esp_hal::rng::Rng; use esp_radio::wifi::{ClientConfig, ScanConfig, WifiController, WifiDevice, WifiEvent}; @@ -66,9 +67,19 @@ pub async fn wifi_connect_task(mut wifi: WifiController<'static>, motion: Dynami } } +#[embassy_executor::task] +pub async fn location_sampler(mut predictions: DynSubscriber<'static, Prediction>, tx: DynSender<'static, Prediction>) { + loop { + if let Prediction::Location(coords) = predictions.next_message_pure().await { + debug!("New location prediction: {coords}"); + tx.send(Prediction::Location(coords)); + } + } +} + // TODO: Wifi task needs to know when there is data to upload, so it only connects when needed. #[embassy_executor::task] -pub async fn http_telemetry_task(mut predictions: DynSubscriber<'static, Prediction>, stack: Stack<'static>, motion: DynamicSender<'static, Measurement>) { +pub async fn http_telemetry_task(mut latest_prediction: DynReceiver<'static, Prediction>, stack: Stack<'static>, motion: DynamicSender<'static, Measurement>) { // TODO: should wait for wifi disconnect event somehow and use that to restart sending the wifi around let seed = Rng::new().random() as i32; @@ -91,25 +102,31 @@ pub async fn http_telemetry_task(mut predictions: DynSubscriber<'static, Predict let mut last_push = Instant::from_ticks(0); loop { - if let Prediction::Location(coords) = predictions.next_message_pure().await { - if stack.is_config_up() { - // Only push to HTTP if we have an ip config etc - if last_push.elapsed().as_secs() >= 5 || gps_to_local_meters_haversine(&last_location, &coords).norm() >= 10.0 { - last_location = coords; - last_push = Instant::now(); - if let Err(e) = Backoff::from_secs(3).attempt(async || { - motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::AcquiringFix)).await; - push_location(&mut client, coords, Instant::now().as_millis()).await - }).await { - motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await; - warn!("Could not submit location! {e:?}"); - } else { - info!("Location published"); - motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Online)).await; - } + motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await; + stack.wait_config_up().await; + info!("Network is up, connecting to nextcloud..."); + motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::AcquiringFix)).await; + + if let Err(err) = ping_nextcloud(&mut client).await { + error!("Could not ping nextcloud: {err:?}"); + continue; + } + + motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Online)).await; + + if let Prediction::Location(coords) = latest_prediction.get().await { + // Only push to HTTP if we have an ip config etc + if last_push.elapsed().as_secs() >= 5 || gps_to_local_meters_haversine(&last_location, &coords).norm() >= 10.0 { + last_location = coords; + last_push = Instant::now(); + if let Err(e) = Backoff::from_secs(3).attempt(async || { + push_location(&mut client, coords, Instant::now().as_millis()).await + }).await { + motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await; + warn!("Could not submit location! {e:?}"); + } else { + info!("Location published"); } - } else { - motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await; } } } @@ -133,4 +150,24 @@ async fn push_location(client: &mut HttpClient<'_, TcpClient<'_, 1, 4096, 4096>, let content = core::str::from_utf8(res).unwrap(); debug!("HTTP response: {content}"); Ok(()) +} + +async fn ping_nextcloud(client: &mut HttpClient<'_, TcpClient<'_, 1, 4096, 4096>, DnsSocket<'_>>) -> Result { + let mut buffer = [0u8; 4096]; + let url = "https://nextcloud.malloc.hackerbots.net/nextcloud/index.php/login"; + info!("Pinging via {url}"); + let mut http_req = client + .request( + reqwless::request::Method::HEAD, + url, + ) + .await?; + let response = http_req.send(&mut buffer).await?; + if !response.status.is_client_error() && !response.status.is_server_error() { + info!("Nextcloud is online!"); + Ok(true) + } else { + warn!("Nextcloud ping returned error status: {:?}", response.status); + Ok(false) + } } \ No newline at end of file