2023-12-01 17:27:04 +00:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
use actix::{Actor, Context, Handler, Message, Recipient};
|
2023-12-04 22:59:26 +00:00
|
|
|
use emgauwa_lib::errors::EmgauwaError;
|
2023-12-01 17:27:04 +00:00
|
|
|
use emgauwa_lib::models::Controller;
|
|
|
|
use emgauwa_lib::types::{ControllerUid, ControllerWsAction};
|
|
|
|
use futures::executor::block_on;
|
|
|
|
use sqlx::{Pool, Sqlite};
|
|
|
|
|
|
|
|
#[derive(Message)]
|
2023-12-04 22:59:26 +00:00
|
|
|
#[rtype(result = "Result<(), EmgauwaError>")]
|
2023-12-01 17:27:04 +00:00
|
|
|
pub struct DisconnectController {
|
|
|
|
pub controller_uid: ControllerUid,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Message)]
|
2023-12-04 22:59:26 +00:00
|
|
|
#[rtype(result = "Result<(), EmgauwaError>")]
|
2023-12-01 17:27:04 +00:00
|
|
|
pub struct ConnectController {
|
|
|
|
pub address: Recipient<ControllerWsAction>,
|
|
|
|
pub controller: Controller,
|
|
|
|
}
|
|
|
|
|
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 {
|
2023-12-01 17:27:04 +00:00
|
|
|
pub pool: Pool<Sqlite>,
|
2023-12-04 22:59:26 +00:00
|
|
|
pub connected_controllers: HashMap<ControllerUid, (Controller, Recipient<ControllerWsAction>)>,
|
2023-12-01 17:27:04 +00:00
|
|
|
}
|
|
|
|
|
2023-12-05 20:57:00 +00:00
|
|
|
impl AppState {
|
|
|
|
pub fn new(pool: Pool<Sqlite>) -> AppState {
|
|
|
|
AppState {
|
2023-12-01 17:27:04 +00:00
|
|
|
pool,
|
2023-12-04 22:59:26 +00:00
|
|
|
connected_controllers: HashMap::new(),
|
2023-12-01 17:27:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-05 20:57:00 +00:00
|
|
|
impl Actor for AppState {
|
2023-12-01 17:27:04 +00:00
|
|
|
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>;
|
2023-12-01 17:27:04 +00:00
|
|
|
|
|
|
|
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())?;
|
2023-12-01 17:27:04 +00:00
|
|
|
|
2023-12-05 15:11:40 +00:00
|
|
|
if let Some((controller, address)) = self.connected_controllers.remove(&msg.controller_uid)
|
|
|
|
{
|
2023-12-01 17:27:04 +00:00
|
|
|
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
|
|
|
|
);
|
|
|
|
}
|
2023-12-05 15:11:40 +00:00
|
|
|
block_on(address.send(ControllerWsAction::Disconnect))??;
|
2023-12-01 17:27:04 +00:00
|
|
|
}
|
|
|
|
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>;
|
2023-12-01 17:27:04 +00:00
|
|
|
|
|
|
|
fn handle(&mut self, msg: ConnectController, _ctx: &mut Self::Context) -> Self::Result {
|
2023-12-04 22:59:26 +00:00
|
|
|
self.connected_controllers
|
|
|
|
.insert(msg.controller.c.uid.clone(), (msg.controller, msg.address));
|
2023-12-01 17:27:04 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2023-12-04 22:59:26 +00:00
|
|
|
|
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 {
|
2023-12-05 15:11:40 +00:00
|
|
|
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) {
|
|
|
|
block_on(address.send(msg.action))?
|
|
|
|
} else {
|
|
|
|
Err(EmgauwaError::Connection(msg.controller_uid))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|