Add ControllerWsAction
This commit is contained in:
		
							parent
							
								
									cb47dcda5c
								
							
						
					
					
						commit
						3b596de06f
					
				
					 10 changed files with 134 additions and 34 deletions
				
			
		| 
						 | 
					@ -2,13 +2,12 @@ openapi: 3.0.0
 | 
				
			||||||
info:
 | 
					info:
 | 
				
			||||||
  contact:
 | 
					  contact:
 | 
				
			||||||
    name: Tobias Reisinger
 | 
					    name: Tobias Reisinger
 | 
				
			||||||
    url: 'https://serguzim.me'
 | 
					    url: 'https://git.serguzim.me/emgauwa/'
 | 
				
			||||||
  title: Emgauwa API v1
 | 
					  title: Emgauwa API v1
 | 
				
			||||||
  version: 0.0.1
 | 
					  version: 0.5.0
 | 
				
			||||||
  description: Server API to manage an Emgauwa system.
 | 
					  description: Server API to manage an Emgauwa system.
 | 
				
			||||||
servers:
 | 
					servers:
 | 
				
			||||||
  - url: 'http://emgauwa-test-raspi.fritz.box'
 | 
					  - url: 'http://localhost:4419'
 | 
				
			||||||
  - url: 'http://localhost:5000'
 | 
					 | 
				
			||||||
tags:
 | 
					tags:
 | 
				
			||||||
  - name: schedules
 | 
					  - name: schedules
 | 
				
			||||||
  - name: relays
 | 
					  - name: relays
 | 
				
			||||||
| 
						 | 
					@ -319,7 +318,7 @@ paths:
 | 
				
			||||||
        '404':
 | 
					        '404':
 | 
				
			||||||
          description: Not Found
 | 
					          description: Not Found
 | 
				
			||||||
      operationId: delete-controllers-controller_id
 | 
					      operationId: delete-controllers-controller_id
 | 
				
			||||||
      description: Delete a single controller. To recover the controller you need to use the conbtrollers/discover feature.
 | 
					      description: Delete a single controller. To recover the controller you need to use the controllers/discover feature.
 | 
				
			||||||
  '/api/v1/controllers/{controller_id}/relays':
 | 
					  '/api/v1/controllers/{controller_id}/relays':
 | 
				
			||||||
    parameters:
 | 
					    parameters:
 | 
				
			||||||
      - schema:
 | 
					      - schema:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ use std::str;
 | 
				
			||||||
use crate::relay_loop::run_relay_loop;
 | 
					use crate::relay_loop::run_relay_loop;
 | 
				
			||||||
use crate::settings::Settings;
 | 
					use crate::settings::Settings;
 | 
				
			||||||
use emgauwa_lib::db::{DbController, DbRelay};
 | 
					use emgauwa_lib::db::{DbController, DbRelay};
 | 
				
			||||||
 | 
					use emgauwa_lib::handlers::v1::ws::controllers::ControllerWsAction;
 | 
				
			||||||
use emgauwa_lib::models::convert_db_list;
 | 
					use emgauwa_lib::models::convert_db_list;
 | 
				
			||||||
use emgauwa_lib::types::ControllerUid;
 | 
					use emgauwa_lib::types::ControllerUid;
 | 
				
			||||||
use emgauwa_lib::{db, models};
 | 
					use emgauwa_lib::{db, models};
 | 
				
			||||||
| 
						 | 
					@ -96,10 +97,6 @@ async fn main() {
 | 
				
			||||||
		relays,
 | 
							relays,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let this_json = serde_json::to_string(&this).unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	println!("{}", this_json);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let url = format!(
 | 
						let url = format!(
 | 
				
			||||||
		"ws://{}:{}/api/v1/ws/controllers",
 | 
							"ws://{}:{}/api/v1/ws/controllers",
 | 
				
			||||||
		settings.core.host, settings.core.port
 | 
							settings.core.host, settings.core.port
 | 
				
			||||||
| 
						 | 
					@ -112,7 +109,11 @@ async fn main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let (mut write, read) = ws_stream.split();
 | 
						let (mut write, read) = ws_stream.split();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	write.send(Message::text(this_json)).await.unwrap();
 | 
						let ws_action = ControllerWsAction::Register(this);
 | 
				
			||||||
 | 
						println!("Sending action: {:?}", ws_action);
 | 
				
			||||||
 | 
						let ws_action_json = serde_json::to_string(&ws_action).unwrap();
 | 
				
			||||||
 | 
						println!("Sending json: {}", ws_action_json);
 | 
				
			||||||
 | 
						write.send(Message::text(ws_action_json)).await.unwrap();
 | 
				
			||||||
	let ws_to_stdout = read.for_each(handle_message);
 | 
						let ws_to_stdout = read.for_each(handle_message);
 | 
				
			||||||
	let stdin_to_ws = stdin_rx.map(Ok).forward(write);
 | 
						let stdin_to_ws = stdin_rx.map(Ok).forward(write);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,6 @@ use tokio::time;
 | 
				
			||||||
pub async fn run_relay_loop(settings: Settings) {
 | 
					pub async fn run_relay_loop(settings: Settings) {
 | 
				
			||||||
	let default_duration = Duration::from_millis(1000);
 | 
						let default_duration = Duration::from_millis(1000);
 | 
				
			||||||
	loop {
 | 
						loop {
 | 
				
			||||||
		// naivetime timestamp for now
 | 
					 | 
				
			||||||
		let next_timestamp = Local::now().naive_local().time() + default_duration;
 | 
							let next_timestamp = Local::now().naive_local().time() + default_duration;
 | 
				
			||||||
		time::sleep(default_duration).await;
 | 
							time::sleep(default_duration).await;
 | 
				
			||||||
		println!("Relay loop: {}", next_timestamp)
 | 
							println!("Relay loop: {}", next_timestamp)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
use serde_derive::Serialize;
 | 
					use serde_derive::{Deserialize, Serialize};
 | 
				
			||||||
use std::ops::DerefMut;
 | 
					use std::ops::DerefMut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use sqlx::pool::PoolConnection;
 | 
					use sqlx::pool::PoolConnection;
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,11 @@ use crate::db::errors::DatabaseError;
 | 
				
			||||||
use crate::db::DbTag;
 | 
					use crate::db::DbTag;
 | 
				
			||||||
use crate::types::ControllerUid;
 | 
					use crate::types::ControllerUid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Serialize, Clone)]
 | 
					#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
				
			||||||
pub struct DbController {
 | 
					pub struct DbController {
 | 
				
			||||||
 | 
						#[serde(skip)]
 | 
				
			||||||
	pub id: i64,
 | 
						pub id: i64,
 | 
				
			||||||
 | 
						#[serde(rename = "id")]
 | 
				
			||||||
	pub uid: ControllerUid,
 | 
						pub uid: ControllerUid,
 | 
				
			||||||
	pub name: String,
 | 
						pub name: String,
 | 
				
			||||||
	pub relay_count: i64,
 | 
						pub relay_count: i64,
 | 
				
			||||||
| 
						 | 
					@ -51,6 +53,19 @@ impl DbController {
 | 
				
			||||||
		.map_err(DatabaseError::from)
 | 
							.map_err(DatabaseError::from)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pub async fn get_by_uid_or_create(
 | 
				
			||||||
 | 
							conn: &mut PoolConnection<Sqlite>,
 | 
				
			||||||
 | 
							uid: &ControllerUid,
 | 
				
			||||||
 | 
							new_name: &str,
 | 
				
			||||||
 | 
							new_relay_count: i64,
 | 
				
			||||||
 | 
							new_active: bool,
 | 
				
			||||||
 | 
						) -> Result<DbController, DatabaseError> {
 | 
				
			||||||
 | 
							match DbController::get_by_uid(conn, uid).await? {
 | 
				
			||||||
 | 
								Some(tag) => Ok(tag),
 | 
				
			||||||
 | 
								None => DbController::create(conn, uid, new_name, new_relay_count, new_active).await,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pub async fn get_by_tag(
 | 
						pub async fn get_by_tag(
 | 
				
			||||||
		conn: &mut PoolConnection<Sqlite>,
 | 
							conn: &mut PoolConnection<Sqlite>,
 | 
				
			||||||
		tag: &DbTag,
 | 
							tag: &DbTag,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
use serde_derive::Serialize;
 | 
					use serde_derive::{Deserialize, Serialize};
 | 
				
			||||||
use std::ops::DerefMut;
 | 
					use std::ops::DerefMut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::db::DbController;
 | 
					use crate::db::DbController;
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ use sqlx::Sqlite;
 | 
				
			||||||
use crate::db::errors::DatabaseError;
 | 
					use crate::db::errors::DatabaseError;
 | 
				
			||||||
use crate::db::DbTag;
 | 
					use crate::db::DbTag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Serialize, Clone, sqlx::FromRow)]
 | 
					#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
				
			||||||
pub struct DbRelay {
 | 
					pub struct DbRelay {
 | 
				
			||||||
	#[serde(skip)]
 | 
						#[serde(skip)]
 | 
				
			||||||
	pub id: i64,
 | 
						pub id: i64,
 | 
				
			||||||
| 
						 | 
					@ -51,6 +51,18 @@ impl DbRelay {
 | 
				
			||||||
		.await?)
 | 
							.await?)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pub async fn get_by_controller_and_num_or_create(
 | 
				
			||||||
 | 
							conn: &mut PoolConnection<Sqlite>,
 | 
				
			||||||
 | 
							controller: &DbController,
 | 
				
			||||||
 | 
							number: i64,
 | 
				
			||||||
 | 
							new_name: &str,
 | 
				
			||||||
 | 
						) -> Result<DbRelay, DatabaseError> {
 | 
				
			||||||
 | 
							match DbRelay::get_by_controller_and_num(conn, controller, number).await? {
 | 
				
			||||||
 | 
								Some(relay) => Ok(relay),
 | 
				
			||||||
 | 
								None => DbRelay::create(conn, new_name, number, controller).await,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pub async fn get_by_tag(
 | 
						pub async fn get_by_tag(
 | 
				
			||||||
		conn: &mut PoolConnection<Sqlite>,
 | 
							conn: &mut PoolConnection<Sqlite>,
 | 
				
			||||||
		tag: &DbTag,
 | 
							tag: &DbTag,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,11 +10,11 @@ use crate::db::model_utils::Period;
 | 
				
			||||||
use crate::db::DbTag;
 | 
					use crate::db::DbTag;
 | 
				
			||||||
use crate::types::ScheduleUid;
 | 
					use crate::types::ScheduleUid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Serialize, Clone)]
 | 
					#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
				
			||||||
pub struct DbSchedule {
 | 
					pub struct DbSchedule {
 | 
				
			||||||
	#[serde(skip)]
 | 
						#[serde(skip)]
 | 
				
			||||||
	pub id: i64,
 | 
						pub id: i64,
 | 
				
			||||||
	#[serde(rename(serialize = "id"))]
 | 
						#[serde(rename = "id")]
 | 
				
			||||||
	pub uid: ScheduleUid,
 | 
						pub uid: ScheduleUid,
 | 
				
			||||||
	pub name: String,
 | 
						pub name: String,
 | 
				
			||||||
	pub periods: DbPeriods,
 | 
						pub periods: DbPeriods,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,22 @@
 | 
				
			||||||
use crate::db::DbSchedule;
 | 
					use crate::db::errors::DatabaseError;
 | 
				
			||||||
 | 
					use crate::db::{DbController, DbRelay};
 | 
				
			||||||
use crate::handlers::errors::ApiError;
 | 
					use crate::handlers::errors::ApiError;
 | 
				
			||||||
 | 
					use crate::models::Controller;
 | 
				
			||||||
use actix::{Actor, StreamHandler};
 | 
					use actix::{Actor, StreamHandler};
 | 
				
			||||||
use actix_web::{get, web, HttpRequest, HttpResponse};
 | 
					use actix_web::{get, web, HttpRequest, HttpResponse};
 | 
				
			||||||
use actix_web_actors::ws;
 | 
					use actix_web_actors::ws;
 | 
				
			||||||
use actix_web_actors::ws::ProtocolError;
 | 
					use actix_web_actors::ws::ProtocolError;
 | 
				
			||||||
 | 
					use futures::FutureExt;
 | 
				
			||||||
 | 
					use serde_derive::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					use sqlx::pool::PoolConnection;
 | 
				
			||||||
use sqlx::{Pool, Sqlite};
 | 
					use sqlx::{Pool, Sqlite};
 | 
				
			||||||
use ws::Message;
 | 
					use ws::Message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub enum ControllerWsAction {
 | 
				
			||||||
 | 
						Register(Controller),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ControllerWs {
 | 
					struct ControllerWs {
 | 
				
			||||||
	pub pool: Pool<Sqlite>,
 | 
						pub pool: Pool<Sqlite>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -15,24 +25,57 @@ impl Actor for ControllerWs {
 | 
				
			||||||
	type Context = ws::WebsocketContext<Self>;
 | 
						type Context = ws::WebsocketContext<Self>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn get_schedules(pool: &mut Pool<Sqlite>) -> Result<Vec<DbSchedule>, ApiError> {
 | 
					 | 
				
			||||||
	let mut pool_conn = pool.acquire().await?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Ok(DbSchedule::get_all(&mut pool_conn).await?)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl StreamHandler<Result<Message, ProtocolError>> for ControllerWs {
 | 
					impl StreamHandler<Result<Message, ProtocolError>> for ControllerWs {
 | 
				
			||||||
	fn handle(&mut self, msg: Result<Message, ProtocolError>, ctx: &mut Self::Context) {
 | 
						fn handle(&mut self, msg: Result<Message, ProtocolError>, ctx: &mut Self::Context) {
 | 
				
			||||||
		let schedules = futures::executor::block_on(get_schedules(&mut self.pool)).unwrap();
 | 
							let mut pool_conn = futures::executor::block_on(self.pool.acquire()).unwrap();
 | 
				
			||||||
		let schedules_json = serde_json::to_string(&schedules).unwrap();
 | 
					
 | 
				
			||||||
		match msg {
 | 
							match msg {
 | 
				
			||||||
			Ok(Message::Ping(msg)) => ctx.pong(&msg),
 | 
								Ok(Message::Ping(msg)) => ctx.pong(&msg),
 | 
				
			||||||
			Ok(Message::Text(text)) => {
 | 
								Ok(Message::Text(text)) => {
 | 
				
			||||||
				println!("Got text: {}", text);
 | 
									let action: ControllerWsAction = serde_json::from_str(&text).unwrap();
 | 
				
			||||||
				ctx.text(schedules_json)
 | 
									let action_res = futures::executor::block_on(handle_action(&mut pool_conn, action));
 | 
				
			||||||
 | 
									if let Err(e) = action_res {
 | 
				
			||||||
 | 
										log::error!("Error handling action: {:?}", e);
 | 
				
			||||||
 | 
										ctx.text(serde_json::to_string(&e).unwrap());
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			_ => {}
 | 
								_ => {}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//let schedules = futures::executor::block_on(DbSchedule::get_all(&mut pool_conn)).unwrap();
 | 
				
			||||||
 | 
							//let schedules_json = serde_json::to_string(&schedules).unwrap();
 | 
				
			||||||
 | 
							//ctx.text(schedules_json);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub async fn handle_action(
 | 
				
			||||||
 | 
						conn: &mut PoolConnection<Sqlite>,
 | 
				
			||||||
 | 
						action: ControllerWsAction,
 | 
				
			||||||
 | 
					) -> Result<(), DatabaseError> {
 | 
				
			||||||
 | 
						match action {
 | 
				
			||||||
 | 
							ControllerWsAction::Register(controller) => {
 | 
				
			||||||
 | 
								log::info!("Registering controller: {:?}", controller);
 | 
				
			||||||
 | 
								let c = &controller.controller;
 | 
				
			||||||
 | 
								let controller_db =
 | 
				
			||||||
 | 
									DbController::get_by_uid_or_create(conn, &c.uid, &c.name, c.relay_count, c.active)
 | 
				
			||||||
 | 
										.await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								println!("Controller: {:?}", controller_db);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for relay in &controller.relays {
 | 
				
			||||||
 | 
									let r = &relay.relay;
 | 
				
			||||||
 | 
									let relay_db = DbRelay::get_by_controller_and_num_or_create(
 | 
				
			||||||
 | 
										conn,
 | 
				
			||||||
 | 
										&controller_db,
 | 
				
			||||||
 | 
										r.number,
 | 
				
			||||||
 | 
										&r.name,
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
									.await?;
 | 
				
			||||||
 | 
									println!("Controller relay: {:?}", relay_db);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Ok(())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
use crate::db;
 | 
					use crate::db;
 | 
				
			||||||
use crate::db::errors::DatabaseError;
 | 
					use crate::db::errors::DatabaseError;
 | 
				
			||||||
use crate::db::{DbRelay, DbSchedule};
 | 
					use crate::db::{DbRelay, DbSchedule};
 | 
				
			||||||
 | 
					use crate::types::ControllerUid;
 | 
				
			||||||
use futures::executor;
 | 
					use futures::executor;
 | 
				
			||||||
use serde_derive::Serialize;
 | 
					use serde_derive::{Deserialize, Serialize};
 | 
				
			||||||
use sqlx::pool::PoolConnection;
 | 
					use sqlx::pool::PoolConnection;
 | 
				
			||||||
use sqlx::Sqlite;
 | 
					use sqlx::Sqlite;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,22 +18,23 @@ pub trait FromDbModel {
 | 
				
			||||||
		Self: Sized;
 | 
							Self: Sized;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Serialize, Debug)]
 | 
					#[derive(Serialize, Deserialize, Debug)]
 | 
				
			||||||
pub struct Schedule {
 | 
					pub struct Schedule {
 | 
				
			||||||
	#[serde(flatten)]
 | 
						#[serde(flatten)]
 | 
				
			||||||
	pub schedule: DbSchedule,
 | 
						pub schedule: DbSchedule,
 | 
				
			||||||
	pub tags: Vec<String>,
 | 
						pub tags: Vec<String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Serialize, Debug)]
 | 
					#[derive(Serialize, Deserialize, Debug)]
 | 
				
			||||||
pub struct Relay {
 | 
					pub struct Relay {
 | 
				
			||||||
	#[serde(flatten)]
 | 
						#[serde(flatten)]
 | 
				
			||||||
	pub relay: DbRelay,
 | 
						pub relay: DbRelay,
 | 
				
			||||||
	pub controller: db::DbController,
 | 
						pub controller: db::DbController,
 | 
				
			||||||
 | 
						pub controller_id: ControllerUid,
 | 
				
			||||||
	pub tags: Vec<String>,
 | 
						pub tags: Vec<String>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Serialize, Debug)]
 | 
					#[derive(Serialize, Deserialize, Debug)]
 | 
				
			||||||
pub struct Controller {
 | 
					pub struct Controller {
 | 
				
			||||||
	#[serde(flatten)]
 | 
						#[serde(flatten)]
 | 
				
			||||||
	pub controller: db::DbController,
 | 
						pub controller: db::DbController,
 | 
				
			||||||
| 
						 | 
					@ -62,11 +64,13 @@ impl FromDbModel for Relay {
 | 
				
			||||||
	) -> Result<Self, DatabaseError> {
 | 
						) -> Result<Self, DatabaseError> {
 | 
				
			||||||
		let relay = db_model.clone();
 | 
							let relay = db_model.clone();
 | 
				
			||||||
		let controller = executor::block_on(relay.get_controller(conn))?;
 | 
							let controller = executor::block_on(relay.get_controller(conn))?;
 | 
				
			||||||
 | 
							let controller_id = controller.uid.clone();
 | 
				
			||||||
		let tags = executor::block_on(relay.get_tags(conn))?;
 | 
							let tags = executor::block_on(relay.get_tags(conn))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Ok(Relay {
 | 
							Ok(Relay {
 | 
				
			||||||
			relay,
 | 
								relay,
 | 
				
			||||||
			controller,
 | 
								controller,
 | 
				
			||||||
 | 
								controller_id,
 | 
				
			||||||
			tags,
 | 
								tags,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,10 @@
 | 
				
			||||||
use serde::{Serialize, Serializer};
 | 
					use serde::{Deserialize, Deserializer, Serialize, Serializer};
 | 
				
			||||||
use sqlx::database::HasArguments;
 | 
					use sqlx::database::HasArguments;
 | 
				
			||||||
use sqlx::encode::IsNull;
 | 
					use sqlx::encode::IsNull;
 | 
				
			||||||
use sqlx::error::BoxDynError;
 | 
					use sqlx::error::BoxDynError;
 | 
				
			||||||
use sqlx::sqlite::{SqliteTypeInfo, SqliteValueRef};
 | 
					use sqlx::sqlite::{SqliteTypeInfo, SqliteValueRef};
 | 
				
			||||||
use sqlx::{Decode, Encode, Sqlite, Type};
 | 
					use sqlx::{Decode, Encode, Sqlite, Type};
 | 
				
			||||||
 | 
					use std::str::FromStr;
 | 
				
			||||||
use uuid::Uuid;
 | 
					use uuid::Uuid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone, Debug)]
 | 
					#[derive(Clone, Debug)]
 | 
				
			||||||
| 
						 | 
					@ -24,6 +25,16 @@ impl Serialize for ControllerUid {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'de> Deserialize<'de> for ControllerUid {
 | 
				
			||||||
 | 
						fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 | 
				
			||||||
 | 
						where
 | 
				
			||||||
 | 
							D: Deserializer<'de>,
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Self::try_from(String::deserialize(deserializer)?.as_str())
 | 
				
			||||||
 | 
								.map_err(|_| serde::de::Error::custom("invalid controller uid"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<&ControllerUid> for String {
 | 
					impl From<&ControllerUid> for String {
 | 
				
			||||||
	fn from(uid: &ControllerUid) -> String {
 | 
						fn from(uid: &ControllerUid) -> String {
 | 
				
			||||||
		uid.0.as_hyphenated().to_string()
 | 
							uid.0.as_hyphenated().to_string()
 | 
				
			||||||
| 
						 | 
					@ -55,6 +66,12 @@ impl<'r> Decode<'r, Sqlite> for ControllerUid {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<&str> for ControllerUid {
 | 
				
			||||||
 | 
						fn from(value: &str) -> Self {
 | 
				
			||||||
 | 
							Self(Uuid::from_str(value).unwrap())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<&[u8]> for ControllerUid {
 | 
					impl From<&[u8]> for ControllerUid {
 | 
				
			||||||
	fn from(value: &[u8]) -> Self {
 | 
						fn from(value: &[u8]) -> Self {
 | 
				
			||||||
		Self(Uuid::from_slice(value).unwrap())
 | 
							Self(Uuid::from_slice(value).unwrap())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ use std::convert::TryFrom;
 | 
				
			||||||
use std::fmt::{Debug, Formatter};
 | 
					use std::fmt::{Debug, Formatter};
 | 
				
			||||||
use std::str::FromStr;
 | 
					use std::str::FromStr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use serde::{Serialize, Serializer};
 | 
					use serde::{Deserialize, Deserializer, Serialize, Serializer};
 | 
				
			||||||
use sqlx::database::HasArguments;
 | 
					use sqlx::database::HasArguments;
 | 
				
			||||||
use sqlx::encode::IsNull;
 | 
					use sqlx::encode::IsNull;
 | 
				
			||||||
use sqlx::error::BoxDynError;
 | 
					use sqlx::error::BoxDynError;
 | 
				
			||||||
| 
						 | 
					@ -75,6 +75,16 @@ impl Serialize for ScheduleUid {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'de> Deserialize<'de> for ScheduleUid {
 | 
				
			||||||
 | 
						fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
 | 
				
			||||||
 | 
						where
 | 
				
			||||||
 | 
							D: Deserializer<'de>,
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Self::try_from(String::deserialize(deserializer)?.as_str())
 | 
				
			||||||
 | 
								.map_err(|_| serde::de::Error::custom("invalid schedule uid"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<Uuid> for ScheduleUid {
 | 
					impl From<Uuid> for ScheduleUid {
 | 
				
			||||||
	fn from(uid: Uuid) -> Self {
 | 
						fn from(uid: Uuid) -> Self {
 | 
				
			||||||
		match uid.as_u128() {
 | 
							match uid.as_u128() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue