core/emgauwa-core/src/app_state.rs

115 lines
3.2 KiB
Rust
Raw Normal View History

use std::collections::HashMap;
use actix::{Actor, Context, Handler, Message, Recipient};
2023-12-04 22:59:26 +00:00
use emgauwa_lib::errors::EmgauwaError;
use emgauwa_lib::models::Controller;
use emgauwa_lib::types::{ControllerUid, ControllerWsAction, RelayStates};
use futures::executor::block_on;
use sqlx::{Pool, Sqlite};
#[derive(Message)]
2023-12-04 22:59:26 +00:00
#[rtype(result = "Result<(), EmgauwaError>")]
pub struct DisconnectController {
pub controller_uid: ControllerUid,
}
#[derive(Message)]
2023-12-04 22:59:26 +00:00
#[rtype(result = "Result<(), EmgauwaError>")]
pub struct ConnectController {
pub address: Recipient<ControllerWsAction>,
pub controller: Controller,
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct UpdateRelayStates {
pub controller_uid: ControllerUid,
pub relay_states: RelayStates,
}
2023-12-04 22:59:26 +00:00
#[derive(Message)]
#[rtype(result = "Result<(), EmgauwaError>")]
pub struct Action {
pub controller_uid: ControllerUid,
pub action: ControllerWsAction,
}
2023-12-05 20:57:00 +00:00
pub struct AppState {
pub pool: Pool<Sqlite>,
2023-12-04 22:59:26 +00:00
pub connected_controllers: HashMap<ControllerUid, (Controller, Recipient<ControllerWsAction>)>,
}
2023-12-05 20:57:00 +00:00
impl AppState {
pub fn new(pool: Pool<Sqlite>) -> AppState {
AppState {
pool,
2023-12-04 22:59:26 +00:00
connected_controllers: HashMap::new(),
}
}
}
2023-12-05 20:57:00 +00:00
impl Actor for AppState {
type Context = Context<Self>;
}
2023-12-05 20:57:00 +00:00
impl Handler<DisconnectController> for AppState {
2023-12-04 22:59:26 +00:00
type Result = Result<(), EmgauwaError>;
fn handle(&mut self, msg: DisconnectController, _ctx: &mut Self::Context) -> Self::Result {
2023-12-04 22:59:26 +00:00
let mut pool_conn = block_on(self.pool.acquire())?;
if let Some((controller, address)) = self.connected_controllers.remove(&msg.controller_uid)
{
if let Err(err) = block_on(controller.c.update_active(&mut pool_conn, false)) {
log::error!(
"Failed to mark controller {} as inactive: {:?}",
controller.c.uid,
err
);
}
// TODO: why does the block_on(send()) version not return? The AppState will be stuck.
//block_on(address.send(ControllerWsAction::Disconnect))??;
address.do_send(ControllerWsAction::Disconnect);
}
Ok(())
}
}
2023-12-05 20:57:00 +00:00
impl Handler<ConnectController> for AppState {
2023-12-04 22:59:26 +00:00
type Result = Result<(), EmgauwaError>;
fn handle(&mut self, msg: ConnectController, _ctx: &mut Self::Context) -> Self::Result {
2024-03-03 21:39:28 +00:00
log::debug!("Connecting controller: {}", msg.controller.c.uid);
2023-12-04 22:59:26 +00:00
self.connected_controllers
.insert(msg.controller.c.uid.clone(), (msg.controller, msg.address));
Ok(())
}
}
2023-12-04 22:59:26 +00:00
impl Handler<UpdateRelayStates> for AppState {
type Result = ();
fn handle(&mut self, msg: UpdateRelayStates, _ctx: &mut Self::Context) -> Self::Result {
if let Some((controller, _)) = self.connected_controllers.get_mut(&msg.controller_uid) {
controller.apply_relay_states(&msg.relay_states);
}
}
}
2023-12-05 20:57:00 +00:00
impl Handler<Action> for AppState {
2023-12-04 22:59:26 +00:00
type Result = Result<(), EmgauwaError>;
fn handle(&mut self, msg: Action, _ctx: &mut Self::Context) -> Self::Result {
log::debug!("Forwarding action: {:?}", msg.action);
2023-12-04 22:59:26 +00:00
if let Some((_, address)) = self.connected_controllers.get(&msg.controller_uid) {
// TODO: why does the block_on(send()) version not return? The AppState will be stuck.
//block_on(address.send(msg.action))?
address.do_send(msg.action);
Ok(())
2023-12-04 22:59:26 +00:00
} else {
Err(EmgauwaError::Connection(msg.controller_uid))
}
}
}