Compare commits

..
3 Commits
Author SHA1 Message Date
mirsal 38f849e323 Implement sensor status debouncing
This introduces a configurable debouncing delay before which no update
is sent to matrix, which avoids flooding the matrix room with updates
when the door is opened and closed in quick succession. It also allows
to quickly open and close the door without sending notifications.

The debouncing window can be configured in config.yml, see example.
2026-10-07 20:17:49 +00:00
mirsal 233a0944c7 Revert "Implement sensor status debouncing"
This reverts commit 0ed1871042.
2026-10-07 13:27:55 +00:00
mirsal 0ed1871042 Implement sensor status debouncing
This introduces a configurable debouncing delay before which no update
is sent to matrix, which avoids flooding the matrix room with updates
when the door is opened and closed in quick succession. It also allows
to quickly open and close the door without sending notifications.

The debouncing window can be configured in config.yml, see example.
2026-10-07 10:52:14 +00:00
+35 -14
View File
@@ -57,7 +57,7 @@ enum DoorSensorStatus {
#[derive(Debug)]
struct LolOpenerState {
sensor_status: Option<DoorSensorStatus>,
update_pending: bool,
pending: Option<(DoorSensorStatus, String)>,
}
#[tokio::main]
@@ -88,7 +88,7 @@ async fn main() -> anyhow::Result<()> {
let current_state = Arc::new(Mutex::new(LolOpenerState {
sensor_status: None,
update_pending: false
pending: None
}));
let current_state = Arc::clone(&current_state);
@@ -100,22 +100,43 @@ async fn main() -> anyhow::Result<()> {
while let Some((new_status, msg)) = debounce_rx.recv().await {
let should_wait = {
//XXX: Panic if the lock is poisoned
let state = current_state.lock().unwrap();
!state.update_pending
let mut state = current_state.lock().unwrap();
let should_wait = state.pending.is_none();
state.pending = Some((new_status, msg));
should_wait
};
if should_wait {
sleep(Duration::from_secs(debounce_delay)).await;
//XXX: Panic if the lock is poisoned
let mut state = current_state.lock().unwrap();
(*state).update_pending = false;
let tx = bcast_tx.clone();
let rooms = rooms.clone();
let state = current_state.clone();
if Some(new_status) != (*state).sensor_status {
debug!("Sending msg {}", msg);
//XXX: Panic if the matrix module can't get the message
bcast_tx.send((msg.into(), rooms.clone())).unwrap();
(*state).sensor_status = Some(new_status);
}
tokio::spawn(async move {
sleep(Duration::from_secs(debounce_delay)).await;
let msg = {
//XXX: Panic if the lock is poisoned
let mut state = state.lock().unwrap();
let pending = state.pending.take();
match pending {
Some((status, msg))
if state.sensor_status.as_ref() != Some(&status) => {
state.sensor_status = Some(status);
Some(msg)
}
_ => None,
}
};
if let Some(msg) = msg {
debug!("Sending msg {}", msg);
//XXX: Panic if the matrix module can't get the message
tx.send((msg, rooms)).unwrap();
}
});
}
}
});