|
|
@@ -3,6 +3,7 @@ use serde::Deserialize;
|
|
|
use sqlx::PgPool;
|
|
|
use uuid::Uuid;
|
|
|
use serde_json::json;
|
|
|
+use rumqttc::{AsyncClient, QoS};
|
|
|
use crate::{
|
|
|
auth::user_auth,
|
|
|
app_error::AppError,
|
|
|
@@ -23,6 +24,7 @@ struct Params {
|
|
|
#[post("/home/{home_id}/device/{device_id}/signal")]
|
|
|
pub async fn route(
|
|
|
db: web::Data<PgPool>,
|
|
|
+ mqtt: web::Data<AsyncClient>,
|
|
|
body: web::Json<Body>,
|
|
|
params: web::Path<Params>,
|
|
|
req: HttpRequest
|
|
|
@@ -32,14 +34,30 @@ pub async fn route(
|
|
|
let device_id = Uuid::parse_str(¶ms.device_id)?;
|
|
|
let device = Device::find_one(&db, user.id, home_id, device_id).await?;
|
|
|
validate_signal(&device.device_type, &body.signal)?;
|
|
|
+ send_signal(device, &body.signal, &mqtt).await?;
|
|
|
Ok(HttpResponse::Ok().json(json!({"success": true})))
|
|
|
}
|
|
|
|
|
|
fn validate_signal(device_type: &DeviceType, signal: &String) -> Result<(), AppError> {
|
|
|
match device_type {
|
|
|
DeviceType::OnOffSwitch => match signal.as_str() {
|
|
|
- "on" | "off" => Ok(()),
|
|
|
+ "ON" | "OFF" => Ok(()),
|
|
|
_ => Err(AppError::invalid_input("Invalid signal for 'on_off_switch'"))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+async fn send_signal(device: Device, signal: &String, client: &AsyncClient) -> Result<(), AppError> {
|
|
|
+ let topic = format!("zigbee2mqtt/{}/set", device.name);
|
|
|
+ let payload = json!({"state": signal});
|
|
|
+
|
|
|
+ match client.publish(
|
|
|
+ &topic,
|
|
|
+ QoS::AtLeastOnce,
|
|
|
+ false,
|
|
|
+ payload.to_string().as_bytes()
|
|
|
+ ).await {
|
|
|
+ Ok(_) => Ok(()),
|
|
|
+ Err(e) => Err(AppError::InternalError(e.to_string()))
|
|
|
+ }
|
|
|
+}
|