|
|
@ -6,12 +6,13 @@ use sprinklers_actors::{ |
|
|
|
|
|
|
|
|
|
|
|
use actix::{fut::wrap_future, Actor, ActorContext, Addr, AsyncContext, Handler, StreamHandler}; |
|
|
|
use actix::{fut::wrap_future, Actor, ActorContext, Addr, AsyncContext, Handler, StreamHandler}; |
|
|
|
use futures_util::TryFutureExt; |
|
|
|
use futures_util::TryFutureExt; |
|
|
|
use sprinklers_core::model::Programs; |
|
|
|
use sprinklers_core::model::{Programs, Zones}; |
|
|
|
use tokio::sync::{broadcast, watch}; |
|
|
|
use tokio::sync::{broadcast, watch}; |
|
|
|
use tracing::{trace, warn}; |
|
|
|
use tracing::{trace, warn}; |
|
|
|
|
|
|
|
|
|
|
|
struct UpdateListenerActor { |
|
|
|
struct UpdateListenerActor { |
|
|
|
mqtt_interface: MqttInterface, |
|
|
|
mqtt_interface: MqttInterface, |
|
|
|
|
|
|
|
old_zones: Option<Zones>, |
|
|
|
old_programs: Option<Programs>, |
|
|
|
old_programs: Option<Programs>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -19,6 +20,7 @@ impl UpdateListenerActor { |
|
|
|
fn new(mqtt_interface: MqttInterface) -> Self { |
|
|
|
fn new(mqtt_interface: MqttInterface) -> Self { |
|
|
|
Self { |
|
|
|
Self { |
|
|
|
mqtt_interface, |
|
|
|
mqtt_interface, |
|
|
|
|
|
|
|
old_zones: None, |
|
|
|
old_programs: None, |
|
|
|
old_programs: None, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -36,6 +38,42 @@ impl Actor for UpdateListenerActor { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl StreamHandler<Zones> for UpdateListenerActor { |
|
|
|
|
|
|
|
fn handle(&mut self, zones: Zones, ctx: &mut Self::Context) { |
|
|
|
|
|
|
|
let mut mqtt_interface = self.mqtt_interface.clone(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let old_zones = self.old_zones.replace(zones.clone()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let fut = async move { |
|
|
|
|
|
|
|
mqtt_interface.publish_zones(&zones).await?; |
|
|
|
|
|
|
|
for zone_id in zones.keys() { |
|
|
|
|
|
|
|
mqtt_interface.publish_zone_state(*zone_id, false).await?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match old_zones { |
|
|
|
|
|
|
|
None => { |
|
|
|
|
|
|
|
mqtt_interface.publish_zones(&zones).await?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Some what of a hack
|
|
|
|
|
|
|
|
// Initialize zone running states to false the first time we
|
|
|
|
|
|
|
|
// receive zones
|
|
|
|
|
|
|
|
for zone_id in zones.keys() { |
|
|
|
|
|
|
|
mqtt_interface.publish_zone_state(*zone_id, false).await?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Some(old_zones) => { |
|
|
|
|
|
|
|
mqtt_interface |
|
|
|
|
|
|
|
.publish_zones_diff(&old_zones, &zones) |
|
|
|
|
|
|
|
.await?; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
.unwrap_or_else(|err: eyre::Report| warn!("could not publish programs: {:?}", err)); |
|
|
|
|
|
|
|
ctx.spawn(wrap_future(fut)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl StreamHandler<Result<ZoneEvent, broadcast::RecvError>> for UpdateListenerActor { |
|
|
|
impl StreamHandler<Result<ZoneEvent, broadcast::RecvError>> for UpdateListenerActor { |
|
|
|
fn handle(&mut self, event: Result<ZoneEvent, broadcast::RecvError>, ctx: &mut Self::Context) { |
|
|
|
fn handle(&mut self, event: Result<ZoneEvent, broadcast::RecvError>, ctx: &mut Self::Context) { |
|
|
|
let event = match event { |
|
|
|
let event = match event { |
|
|
@ -196,6 +234,12 @@ where |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Listenable<UpdateListenerActor> for watch::Receiver<Zones> { |
|
|
|
|
|
|
|
fn listen(self, ctx: &mut <UpdateListenerActor as Actor>::Context) { |
|
|
|
|
|
|
|
ctx.add_stream(self); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Listenable<UpdateListenerActor> for ZoneEventRecv { |
|
|
|
impl Listenable<UpdateListenerActor> for ZoneEventRecv { |
|
|
|
fn listen(self, ctx: &mut <UpdateListenerActor as Actor>::Context) { |
|
|
|
fn listen(self, ctx: &mut <UpdateListenerActor as Actor>::Context) { |
|
|
|
ctx.add_stream(self); |
|
|
|
ctx.add_stream(self); |
|
|
@ -237,6 +281,10 @@ impl UpdateListener { |
|
|
|
self.addr.do_send(Listen(listener)); |
|
|
|
self.addr.do_send(Listen(listener)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn listen_zones(&mut self, zones: watch::Receiver<Zones>) { |
|
|
|
|
|
|
|
self.listen(zones); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub fn listen_zone_events(&mut self, zone_events: ZoneEventRecv) { |
|
|
|
pub fn listen_zone_events(&mut self, zone_events: ZoneEventRecv) { |
|
|
|
self.listen(zone_events); |
|
|
|
self.listen(zone_events); |
|
|
|
} |
|
|
|
} |
|
|
|