From c529335eacd056756ebd757c6eef78ceaeb20dae Mon Sep 17 00:00:00 2001 From: fdiniello Date: Sun, 23 Jul 2023 18:53:49 +0200 Subject: [PATCH] Antennas basic endpoints (#4) Co-authored-by: Felipe Diniello Reviewed-on: https://git.33kbps.com.ar/fdiniello/KairoXYZ/pulls/4 --- Cargo.toml | 3 +- kairo-common/Cargo.toml | 2 + kairo-common/diesel.toml | 9 +++ kairo-common/migrations/.keep | 0 .../down.sql | 6 ++ .../up.sql | 36 +++++++++ .../down.sql | 3 + .../2023-06-18-164844_create_antennas/up.sql | 10 +++ kairo-common/src/lib.rs | 11 ++- kairo-common/src/models/antenna.rs | 20 ++++- kairo-common/src/postgres.rs | 25 ++++++ kairo-common/src/schema.rs | 13 ++++ kairo-core/Cargo.toml | 4 + kairo-core/src/antennas.rs | 77 +++++++++++++++++++ kairo-core/src/main.rs | 32 +++++++- xyz-engine/src/main.rs | 4 +- 16 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 kairo-common/diesel.toml create mode 100644 kairo-common/migrations/.keep create mode 100644 kairo-common/migrations/00000000000000_diesel_initial_setup/down.sql create mode 100644 kairo-common/migrations/00000000000000_diesel_initial_setup/up.sql create mode 100644 kairo-common/migrations/2023-06-18-164844_create_antennas/down.sql create mode 100644 kairo-common/migrations/2023-06-18-164844_create_antennas/up.sql create mode 100644 kairo-common/src/postgres.rs create mode 100644 kairo-common/src/schema.rs create mode 100644 kairo-core/src/antennas.rs diff --git a/Cargo.toml b/Cargo.toml index d32d81a..ef8d3fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,4 +18,5 @@ dotenv = "0.15.0" chrono = "0.4.24" paho-mqtt = "0.12.1" serde = "1.0.162" -serde_json = { version = "1.0.95" } \ No newline at end of file +serde_json = { version = "1.0.95" } +diesel = { version = "2.1.0", features = ["postgres", "extras"] } diff --git a/kairo-common/Cargo.toml b/kairo-common/Cargo.toml index 020e03a..9556c19 100644 --- a/kairo-common/Cargo.toml +++ b/kairo-common/Cargo.toml @@ -14,6 +14,8 @@ dotenv = { workspace = true } chrono = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +diesel = { workspace = true } + influxdb2 = "0.4.2" influxdb2-structmap = "0.2" diff --git a/kairo-common/diesel.toml b/kairo-common/diesel.toml new file mode 100644 index 0000000..c028f4a --- /dev/null +++ b/kairo-common/diesel.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId"] + +[migrations_directory] +dir = "migrations" diff --git a/kairo-common/migrations/.keep b/kairo-common/migrations/.keep new file mode 100644 index 0000000..e69de29 diff --git a/kairo-common/migrations/00000000000000_diesel_initial_setup/down.sql b/kairo-common/migrations/00000000000000_diesel_initial_setup/down.sql new file mode 100644 index 0000000..a9f5260 --- /dev/null +++ b/kairo-common/migrations/00000000000000_diesel_initial_setup/down.sql @@ -0,0 +1,6 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + +DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); +DROP FUNCTION IF EXISTS diesel_set_updated_at(); diff --git a/kairo-common/migrations/00000000000000_diesel_initial_setup/up.sql b/kairo-common/migrations/00000000000000_diesel_initial_setup/up.sql new file mode 100644 index 0000000..d68895b --- /dev/null +++ b/kairo-common/migrations/00000000000000_diesel_initial_setup/up.sql @@ -0,0 +1,36 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + + + + +-- Sets up a trigger for the given table to automatically set a column called +-- `updated_at` whenever the row is modified (unless `updated_at` was included +-- in the modified columns) +-- +-- # Example +-- +-- ```sql +-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); +-- +-- SELECT diesel_manage_updated_at('users'); +-- ``` +CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +BEGIN + EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s + FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +BEGIN + IF ( + NEW IS DISTINCT FROM OLD AND + NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at + ) THEN + NEW.updated_at := current_timestamp; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; diff --git a/kairo-common/migrations/2023-06-18-164844_create_antennas/down.sql b/kairo-common/migrations/2023-06-18-164844_create_antennas/down.sql new file mode 100644 index 0000000..8e1248e --- /dev/null +++ b/kairo-common/migrations/2023-06-18-164844_create_antennas/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` + +DROP TABLE antennas; \ No newline at end of file diff --git a/kairo-common/migrations/2023-06-18-164844_create_antennas/up.sql b/kairo-common/migrations/2023-06-18-164844_create_antennas/up.sql new file mode 100644 index 0000000..57332ea --- /dev/null +++ b/kairo-common/migrations/2023-06-18-164844_create_antennas/up.sql @@ -0,0 +1,10 @@ +-- Your SQL goes here + +CREATE TABLE antennas ( + id VARCHAR(17) PRIMARY KEY, + tssi DOUBLE PRECISION NOT NULL, + pos_x DOUBLE PRECISION NOT NULL, + pos_y DOUBLE PRECISION NOT NULL, + pos_z DOUBLE PRECISION NOT NULL, + comment TEXT +); \ No newline at end of file diff --git a/kairo-common/src/lib.rs b/kairo-common/src/lib.rs index 13f254b..e126a27 100644 --- a/kairo-common/src/lib.rs +++ b/kairo-common/src/lib.rs @@ -4,12 +4,12 @@ #![allow(confusable_idents)] pub mod influx; +pub mod postgres; -// random functions for mqtt +// random functions for mqtt pub mod mqtt; pub mod unit_conversion; - // Commonly used types across the services mod types { pub mod mac; // deprecated for the time being. @@ -18,7 +18,8 @@ mod types { pub type Point = types::point::Point; pub type MAC = types::mac::MAC; - +// DB models: for SQL with Diesel and InfluxDB and influxdb-derive +pub mod schema; mod models { pub mod antenna; pub mod beacon_measure; @@ -30,8 +31,10 @@ mod models { pub data: Vec, } } -pub type Antenna = models::antenna::Antenna; pub type DeviceReport = models::DeviceReport; + +pub type Antenna = models::antenna::Antenna; + pub type KnownPosition = models::known_position::KnownPosition; pub type DynamicDeviceStatus = models::dynamic_device_status::DynamicDeviceStatus; pub type BeaconMeasure = models::beacon_measure::BeaconMeasure; diff --git a/kairo-common/src/models/antenna.rs b/kairo-common/src/models/antenna.rs index 9d8faf8..d7f494c 100644 --- a/kairo-common/src/models/antenna.rs +++ b/kairo-common/src/models/antenna.rs @@ -1,15 +1,27 @@ +use diesel::prelude::*; use std::f64::consts::PI; use crate::{unit_conversion::UnitsConversion, Point}; -#[derive(Debug, Clone, Default)] +#[derive( + Debug, + Clone, + Queryable, + Selectable, + Insertable, + AsChangeset, + serde::Serialize, + serde::Deserialize, +)] +#[diesel(check_for_backend(diesel::pg::Pg))] +#[diesel(table_name = crate::schema::antennas)] pub struct Antenna { pub id: String, pub tssi: f64, + pub pos_x: f64, + pub pos_y: f64, + pub pos_z: f64, pub comment: Option, - pos_x: f64, - pos_y: f64, - pos_z: f64, } impl Antenna { diff --git a/kairo-common/src/postgres.rs b/kairo-common/src/postgres.rs new file mode 100644 index 0000000..68d5acc --- /dev/null +++ b/kairo-common/src/postgres.rs @@ -0,0 +1,25 @@ +use diesel::prelude::*; +use diesel::r2d2::{ConnectionManager, Pool, PooledConnection}; + +pub type DbConn = diesel::pg::PgConnection; +pub type DbPool = Pool>; +pub struct DbPooledConn(pub PooledConnection>); + +pub fn establish_connection() -> DbConn { + let database_url = dotenv::var("DATABASE_URL").expect("DATABASE_URL must be set"); + PgConnection::establish(&database_url) + .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) +} + +pub fn init_pool() -> DbPool { + let database_url = dotenv::var("DATABASE_URL").expect("DATABASE_URL must be set"); + let manager = ConnectionManager::::new(database_url); + DbPool::new(manager).expect("Error connecting to DB") +} + +impl std::ops::Deref for DbPooledConn { + type Target = PgConnection; + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/kairo-common/src/schema.rs b/kairo-common/src/schema.rs new file mode 100644 index 0000000..d0a6a02 --- /dev/null +++ b/kairo-common/src/schema.rs @@ -0,0 +1,13 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + antennas (id) { + #[max_length = 17] + id -> Varchar, + tssi -> Float8, + pos_x -> Float8, + pos_y -> Float8, + pos_z -> Float8, + comment -> Nullable, + } +} diff --git a/kairo-core/Cargo.toml b/kairo-core/Cargo.toml index c7449b1..c86cad7 100644 --- a/kairo-core/Cargo.toml +++ b/kairo-core/Cargo.toml @@ -6,3 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +diesel = { workspace = true} + +rocket = { version = "0.5.0-rc.3", features = ["json"] } +kairo-common = { path = "../kairo-common" } \ No newline at end of file diff --git a/kairo-core/src/antennas.rs b/kairo-core/src/antennas.rs new file mode 100644 index 0000000..2144bcb --- /dev/null +++ b/kairo-core/src/antennas.rs @@ -0,0 +1,77 @@ +use diesel::prelude::*; +use rocket::{http::Status, serde::json::Json, State}; + +use kairo_common::{postgres, schema::antennas, Antenna}; + +#[rocket::get("/id/")] +pub fn get_by_id(db_pool: &State, id: String) -> Option> { + let mut db = db_pool.get().unwrap(); + + let res = antennas::table + .select(antennas::all_columns) + .find(id) + .get_result::(&mut db); + + match res { + Ok(v) => Some(rocket::serde::json::Json(v)), + _ => None, + } +} + +#[rocket::get("/")] +pub fn get_list(db_pool: &State) -> Json> { + let mut db = db_pool.get().unwrap(); + + let res = antennas::table + .select(antennas::all_columns) + .load::(&mut db); + + match res { + Ok(v) => rocket::serde::json::Json(v), + _ => rocket::serde::json::Json(vec![]), + } +} + +#[rocket::post("/new", format = "json", data = "")] +pub fn new(db_pool: &State, antenna: Json) -> Status { + let mut db = db_pool.get().unwrap(); + + let res = diesel::insert_into(antennas::table) + .values(antenna.0) + .execute(&mut db); + + match res { + Ok(_) => Status::Ok, + _ => Status::NotAcceptable, + } +} + +#[rocket::patch("/update", format = "json", data = "")] +pub fn update(db_pool: &State, antenna: Json) -> Status { + let mut db = db_pool.get().unwrap(); + + let res = diesel::update(antennas::table) + .filter(antennas::id.eq(antenna.id.clone())) + .set(antenna.0) + .execute(&mut db); + + match res { + Ok(0) => Status::NotModified, + Ok(1) => Status::Ok, + _ => Status::BadRequest, + } +} + +#[rocket::delete("/delete/")] +pub fn delete(db_pool: &State, id: String) -> Status { + let mut db = db_pool.get().unwrap(); + + let res = diesel::delete(antennas::table) + .filter( antennas::id.eq(id) ) + .execute(&mut db); + + match res { + Ok(1) => Status::Ok, + _ => Status::BadRequest, + } +} diff --git a/kairo-core/src/main.rs b/kairo-core/src/main.rs index e7a11a9..b8f0fd9 100644 --- a/kairo-core/src/main.rs +++ b/kairo-core/src/main.rs @@ -1,3 +1,31 @@ -fn main() { - println!("Hello, world!"); +#[macro_use] +extern crate rocket; + +mod antennas; + +use std::path::{Path, PathBuf}; + +use rocket::fs::NamedFile; +use rocket::response::status::NotFound; + +use kairo_common::postgres; + +#[get("/")] +async fn serve_file(file: PathBuf) -> Result> { + let path = Path::new("static/").join(file); + NamedFile::open(&path) + .await + .map_err(|e| NotFound(e.to_string())) +} + +#[launch] +fn rocket() -> _ { + rocket::build() + .manage(postgres::init_pool()) + .mount("/static", routes![serve_file]) + .mount("/antennas/", routes![antennas::get_by_id]) + .mount("/antennas/", routes![antennas::get_list]) + .mount("/antennas/", routes![antennas::delete]) + .mount("/antennas/", routes![antennas::update]) + .mount("/antennas/", routes![antennas::new]) } diff --git a/xyz-engine/src/main.rs b/xyz-engine/src/main.rs index 4e08638..240fbcf 100644 --- a/xyz-engine/src/main.rs +++ b/xyz-engine/src/main.rs @@ -3,9 +3,7 @@ use futures::stream::StreamExt; mod handler; mod position_solver; -use kairo_common::mqtt::for_async::{ - get_mqtt_cli_and_stream, mqtt_cli_reconnect, mqtt_subscribe, -}; +use kairo_common::mqtt::for_async::{get_mqtt_cli_and_stream, mqtt_cli_reconnect, mqtt_subscribe}; #[tokio::main] async fn main() {