tasks: wifi: expose cloud sensor state through a regular ping of nextcloud
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
use alloc::string::{String, ToString};
|
use alloc::string::ToString;
|
||||||
use embassy_sync::channel::DynamicSender;
|
use embassy_sync::channel::DynamicSender;
|
||||||
use embassy_sync::pubsub::DynSubscriber;
|
use embassy_sync::pubsub::DynSubscriber;
|
||||||
|
use embassy_sync::watch::{DynReceiver, DynSender};
|
||||||
use embassy_time::{Duration, Instant, Timer, WithTimeout};
|
use embassy_time::{Duration, Instant, Timer, WithTimeout};
|
||||||
use esp_hal::rng::Rng;
|
use esp_hal::rng::Rng;
|
||||||
use esp_radio::wifi::{ClientConfig, ScanConfig, WifiController, WifiDevice, WifiEvent};
|
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.
|
// TODO: Wifi task needs to know when there is data to upload, so it only connects when needed.
|
||||||
#[embassy_executor::task]
|
#[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
|
// TODO: should wait for wifi disconnect event somehow and use that to restart sending the wifi around
|
||||||
|
|
||||||
let seed = Rng::new().random() as i32;
|
let seed = Rng::new().random() as i32;
|
||||||
@@ -91,26 +102,32 @@ pub async fn http_telemetry_task(mut predictions: DynSubscriber<'static, Predict
|
|||||||
let mut last_push = Instant::from_ticks(0);
|
let mut last_push = Instant::from_ticks(0);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Prediction::Location(coords) = predictions.next_message_pure().await {
|
motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await;
|
||||||
if stack.is_config_up() {
|
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
|
// 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 {
|
if last_push.elapsed().as_secs() >= 5 || gps_to_local_meters_haversine(&last_location, &coords).norm() >= 10.0 {
|
||||||
last_location = coords;
|
last_location = coords;
|
||||||
last_push = Instant::now();
|
last_push = Instant::now();
|
||||||
if let Err(e) = Backoff::from_secs(3).attempt(async || {
|
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
|
push_location(&mut client, coords, Instant::now().as_millis()).await
|
||||||
}).await {
|
}).await {
|
||||||
motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await;
|
motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await;
|
||||||
warn!("Could not submit location! {e:?}");
|
warn!("Could not submit location! {e:?}");
|
||||||
} else {
|
} else {
|
||||||
info!("Location published");
|
info!("Location published");
|
||||||
motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Online)).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
motion.send(Measurement::SensorHardwareStatus(SensorSource::Cloud, SensorState::Offline)).await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,3 +151,23 @@ async fn push_location(client: &mut HttpClient<'_, TcpClient<'_, 1, 4096, 4096>,
|
|||||||
debug!("HTTP response: {content}");
|
debug!("HTTP response: {content}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn ping_nextcloud(client: &mut HttpClient<'_, TcpClient<'_, 1, 4096, 4096>, DnsSocket<'_>>) -> Result<bool, reqwless::Error> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user