Compare commits
5 commits
c8a70b5a32
...
87416e5af9
Author | SHA1 | Date | |
---|---|---|---|
Mika Bomm | 87416e5af9 | ||
Mika Bomm | 38a0f4d189 | ||
Mika Bomm | a696a05595 | ||
Mika Bomm | ec8859b59c | ||
Mika Bomm | a65657aea1 |
11
ApfelBruno/Data/get data from last hour.bru
Normal file
11
ApfelBruno/Data/get data from last hour.bru
Normal file
|
@ -0,0 +1,11 @@
|
|||
meta {
|
||||
name: get data from last hour
|
||||
type: http
|
||||
seq: 1
|
||||
}
|
||||
|
||||
get {
|
||||
url: http://localhost:8080/api/v1/data
|
||||
body: none
|
||||
auth: none
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
meta {
|
||||
name: Create node group
|
||||
type: http
|
||||
seq: 3
|
||||
seq: 1
|
||||
}
|
||||
|
||||
post {
|
|
@ -12,9 +12,7 @@ post {
|
|||
|
||||
body:json {
|
||||
{
|
||||
"name":"some mac address",
|
||||
"coord_la":1.123123,
|
||||
"coord_lo":5.3123123,
|
||||
"group":"efbd70a9-dc89-4c8d-9e6c-e7607c823df3"
|
||||
"id":"04-7c-16-06-b3-53",
|
||||
"group":"22da4165-582c-4df9-a911-dfd5573ae468"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
meta {
|
||||
name: delete node
|
||||
type: http
|
||||
seq: 4
|
||||
seq: 3
|
||||
}
|
||||
|
||||
delete {
|
||||
|
|
63
Cargo.lock
generated
63
Cargo.lock
generated
|
@ -543,12 +543,16 @@ dependencies = [
|
|||
"actix-cors",
|
||||
"actix-web",
|
||||
"argon2",
|
||||
"chrono",
|
||||
"deku",
|
||||
"dotenvy",
|
||||
"entity",
|
||||
"eui48",
|
||||
"futures",
|
||||
"jsonwebtoken",
|
||||
"sea-orm",
|
||||
"serde",
|
||||
"tokio",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
|
@ -773,8 +777,10 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
|||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
|
@ -950,6 +956,7 @@ dependencies = [
|
|||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
|
@ -964,6 +971,31 @@ dependencies = [
|
|||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deku"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9711031e209dc1306d66985363b4397d4c7b911597580340b93c9729b55f6eb"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"deku_derive",
|
||||
"no_std_io2",
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deku_derive"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58cb0719583cbe4e81fb40434ace2f0d22ccc3e39a74bb3796c22b451b4f139d"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.79",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.9"
|
||||
|
@ -1108,6 +1140,16 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eui48"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "887418ac5e8d57c2e66e04bdc2fe15f9a5407be20b54a82c86bd0e368b709701"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"rustc-serialize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.3"
|
||||
|
@ -1758,6 +1800,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "no_std_io2"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a3564ce7035b1e4778d8cb6cacebb5d766b5e8fe5a75b9e441e33fb61a872c6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
|
@ -2313,6 +2364,12 @@ version = "0.1.24"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-serialize"
|
||||
version = "0.3.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
|
@ -2365,6 +2422,12 @@ dependencies = [
|
|||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
|
|
|
@ -18,3 +18,7 @@ sea-orm = { version = "1", features = [
|
|||
dotenvy = "*"
|
||||
jsonwebtoken = "*"
|
||||
futures = "*"
|
||||
chrono = "*"
|
||||
eui48 = "*"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
deku = "*"
|
||||
|
|
|
@ -1,45 +1,129 @@
|
|||
use crate::AppState;
|
||||
use actix_web::{error::ErrorInternalServerError, web, HttpResponse, Responder};
|
||||
use entity::node_group;
|
||||
use sea_orm::{ActiveModelTrait, ActiveValue, EntityTrait};
|
||||
use actix_web::{
|
||||
error::{ErrorBadRequest, ErrorInternalServerError},
|
||||
web, Responder,
|
||||
};
|
||||
use chrono::Utc;
|
||||
use entity::{node, node_group, sensor_data};
|
||||
use sea_orm::{entity::*, query::*, ActiveModelTrait, ActiveValue, EntityTrait};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct NodeWithSensorData {
|
||||
node: NodeWithMac,
|
||||
sensor_data: Vec<sensor_data::Model>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CreateGroupWithoutId {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CreateLicense {
|
||||
name: String,
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct NodeWithMac {
|
||||
mac: String,
|
||||
coord_la: f64,
|
||||
coord_lo: f64,
|
||||
battery_minimum: f64,
|
||||
battery_maximum: f64,
|
||||
group: uuid::Uuid,
|
||||
}
|
||||
|
||||
impl From<node::Model> for NodeWithMac {
|
||||
fn from(value: node::Model) -> Self {
|
||||
let mac_id_bytes = value.id.to_be_bytes();
|
||||
let mut mac_bytes: [u8; 6] = [0; 6];
|
||||
mac_bytes.copy_from_slice(&mac_id_bytes[2..]);
|
||||
let mac = eui48::MacAddress::new(mac_bytes).to_string(eui48::MacAddressFormat::Canonical);
|
||||
|
||||
Self {
|
||||
mac,
|
||||
coord_la: value.coord_la,
|
||||
coord_lo: value.coord_lo,
|
||||
battery_minimum: value.battery_minimum,
|
||||
battery_maximum: value.battery_maximum,
|
||||
group: value.group,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<node::Model> for NodeWithMac {
|
||||
type Error = eui48::ParseError;
|
||||
|
||||
fn try_into(self) -> Result<node::Model, Self::Error> {
|
||||
let mac = eui48::MacAddress::parse_str(&self.mac)?;
|
||||
let mac_bytes = mac.to_array();
|
||||
let mut mac_id_bytes: [u8; 8] = [0; 8];
|
||||
mac_id_bytes[2..].copy_from_slice(&mac_bytes);
|
||||
let mac_id = i64::from_be_bytes(mac_id_bytes);
|
||||
Ok(node::Model {
|
||||
id: mac_id,
|
||||
coord_la: self.coord_la,
|
||||
coord_lo: self.coord_lo,
|
||||
battery_minimum: self.battery_minimum,
|
||||
battery_maximum: self.battery_maximum,
|
||||
group: self.group,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct GroupWithNode {
|
||||
#[serde(flatten)]
|
||||
group: entity::node_group::Model,
|
||||
node: Vec<entity::node::Model>,
|
||||
group: node_group::Model,
|
||||
node: Vec<NodeWithMac>,
|
||||
}
|
||||
|
||||
pub async fn get_nodes(state: web::Data<AppState>) -> actix_web::Result<impl Responder> {
|
||||
let db = &state.db;
|
||||
|
||||
let result = node_group::Entity::find()
|
||||
let result: Vec<GroupWithNode> = node_group::Entity::find()
|
||||
.find_with_related(entity::prelude::Node)
|
||||
.all(db)
|
||||
.await
|
||||
.map_err(ErrorInternalServerError)?
|
||||
.into_iter()
|
||||
.map(|(group, node)| GroupWithNode { group, node })
|
||||
.map(|(group, nodes)| {
|
||||
let nodes = nodes
|
||||
.into_iter()
|
||||
.map(|n| n.into())
|
||||
.collect::<Vec<NodeWithMac>>();
|
||||
GroupWithNode { group, node: nodes }
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(web::Json(result))
|
||||
}
|
||||
|
||||
pub async fn get_data(state: web::Data<AppState>) -> actix_web::Result<impl Responder> {
|
||||
let db = &state.db;
|
||||
|
||||
let nodes = node::Entity::find()
|
||||
.all(db)
|
||||
.await
|
||||
.map_err(ErrorInternalServerError)?;
|
||||
|
||||
let now = Utc::now();
|
||||
let one_hour_ago = now - chrono::Duration::hours(1);
|
||||
|
||||
let mut result: Vec<NodeWithSensorData> = Vec::new();
|
||||
for node in nodes {
|
||||
let sensor_data = sensor_data::Entity::find()
|
||||
.filter(sensor_data::Column::NodeId.eq(node.id))
|
||||
.filter(sensor_data::Column::Timestamp.gt(one_hour_ago))
|
||||
.all(db)
|
||||
.await
|
||||
.map_err(ErrorInternalServerError)?;
|
||||
|
||||
result.push(NodeWithSensorData {
|
||||
node: node.into(),
|
||||
sensor_data,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(web::Json(result))
|
||||
}
|
||||
|
||||
pub async fn create_group(
|
||||
state: web::Data<AppState>,
|
||||
group: web::Json<CreateGroupWithoutId>,
|
||||
|
@ -60,11 +144,11 @@ pub async fn create_group(
|
|||
|
||||
pub async fn create_node(
|
||||
state: web::Data<AppState>,
|
||||
node: web::Json<CreateLicense>,
|
||||
node_request: web::Json<NodeWithMac>,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let db = &state.db;
|
||||
|
||||
let node = node.into_inner();
|
||||
let node: NodeWithMac = node_request.into_inner();
|
||||
|
||||
println!("Checking group ID: {:?}", node.group);
|
||||
|
||||
|
@ -78,26 +162,17 @@ pub async fn create_node(
|
|||
return Err(ErrorInternalServerError("Group ID does not exist"));
|
||||
}
|
||||
|
||||
let node = entity::node::ActiveModel {
|
||||
id: ActiveValue::NotSet,
|
||||
name: ActiveValue::Set(node.name),
|
||||
status: ActiveValue::NotSet,
|
||||
coord_la: ActiveValue::Set(node.coord_la),
|
||||
coord_lo: ActiveValue::Set(node.coord_lo),
|
||||
temperature: ActiveValue::NotSet,
|
||||
battery_minimum: ActiveValue::NotSet,
|
||||
battery_current: ActiveValue::NotSet,
|
||||
battery_maximum: ActiveValue::NotSet,
|
||||
voltage: ActiveValue::NotSet,
|
||||
uptime: ActiveValue::NotSet,
|
||||
group: ActiveValue::Set(node.group),
|
||||
};
|
||||
let node: node::Model = node
|
||||
.try_into()
|
||||
.map_err(|_| ErrorBadRequest("Invalid Mac Address"))?;
|
||||
let node = node.into_active_model();
|
||||
|
||||
let result = node.insert(db).await.map_err(ErrorInternalServerError)?;
|
||||
|
||||
Ok(web::Json(result))
|
||||
}
|
||||
|
||||
/*
|
||||
pub async fn delete_node(
|
||||
state: web::Data<AppState>,
|
||||
path: web::Path<Uuid>,
|
||||
|
@ -113,3 +188,4 @@ pub async fn delete_node(
|
|||
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use actix_web::{web, App, HttpServer};
|
||||
use deku::prelude::*;
|
||||
use sea_orm::{Database, DatabaseConnection};
|
||||
use std::env;
|
||||
use tokio::{io::AsyncReadExt, net::TcpListener};
|
||||
|
||||
mod controller;
|
||||
|
||||
|
@ -13,6 +15,14 @@ struct AppState {
|
|||
secret: String,
|
||||
}
|
||||
|
||||
#[derive(DekuRead, DekuWrite, Debug)]
|
||||
struct Data {
|
||||
mac: [u8; 6],
|
||||
temp: f32,
|
||||
battery_voltage: f32,
|
||||
up_time: u32,
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -30,10 +40,36 @@ async fn main() -> std::io::Result<()> {
|
|||
println!("Finished running migrations");
|
||||
|
||||
let state = AppState {
|
||||
db: conn,
|
||||
db: conn.clone(),
|
||||
secret: jwt_secret,
|
||||
};
|
||||
|
||||
tokio::spawn(async {
|
||||
let db = conn;
|
||||
let listener = TcpListener::bind("0.0.0.0:7999")
|
||||
.await
|
||||
.expect("Couldnt bind to port 7999");
|
||||
|
||||
loop {
|
||||
if let Ok((mut stream, _)) = listener.accept().await {
|
||||
let mut buffer = vec![0; 1024];
|
||||
loop {
|
||||
if let Ok(size) = stream.read(&mut buffer).await {
|
||||
buffer.truncate(size);
|
||||
if let Ok((data, _)) = Data::from_bytes((&buffer, 0)) {
|
||||
println!("Received: {:?}", data);
|
||||
// Process the data or save it to the database
|
||||
} else {
|
||||
println!("Failed to parse data");
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
println!("Listening for connections...");
|
||||
HttpServer::new(move || {
|
||||
let cors = if cfg!(debug_assertions) {
|
||||
|
|
|
@ -19,7 +19,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||
.get(node::get_nodes)
|
||||
.post(node::create_node),
|
||||
)
|
||||
.service(web::resource("/nodes/{id}").delete(node::delete_node))
|
||||
.service(web::resource("/data").get(node::get_data))
|
||||
//.service(web::resource("/nodes/{id}").delete(node::delete_node))
|
||||
.service(web::resource("/groups").post(node::create_group)),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,4 +4,5 @@ pub mod prelude;
|
|||
|
||||
pub mod node;
|
||||
pub mod node_group;
|
||||
pub mod sensor_data;
|
||||
pub mod user;
|
||||
|
|
|
@ -7,24 +7,15 @@ use serde::{Deserialize, Serialize};
|
|||
#[sea_orm(table_name = "node")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub status: bool,
|
||||
pub id: i64,
|
||||
#[sea_orm(column_type = "Double")]
|
||||
pub coord_la: f64,
|
||||
#[sea_orm(column_type = "Double")]
|
||||
pub coord_lo: f64,
|
||||
#[sea_orm(column_type = "Float")]
|
||||
pub temperature: f32,
|
||||
#[sea_orm(column_type = "Double")]
|
||||
pub battery_minimum: f64,
|
||||
#[sea_orm(column_type = "Double")]
|
||||
pub battery_current: f64,
|
||||
#[sea_orm(column_type = "Double")]
|
||||
pub battery_maximum: f64,
|
||||
#[sea_orm(column_type = "Double")]
|
||||
pub voltage: f64,
|
||||
pub uptime: i64,
|
||||
pub group: Uuid,
|
||||
}
|
||||
|
||||
|
@ -38,6 +29,8 @@ pub enum Relation {
|
|||
on_delete = "Cascade"
|
||||
)]
|
||||
NodeGroup,
|
||||
#[sea_orm(has_many = "super::sensor_data::Entity")]
|
||||
SensorData,
|
||||
}
|
||||
|
||||
impl Related<super::node_group::Entity> for Entity {
|
||||
|
@ -46,4 +39,10 @@ impl Related<super::node_group::Entity> for Entity {
|
|||
}
|
||||
}
|
||||
|
||||
impl Related<super::sensor_data::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::SensorData.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
pub use super::node::Entity as Node;
|
||||
pub use super::node_group::Entity as NodeGroup;
|
||||
pub use super::sensor_data::Entity as SensorData;
|
||||
pub use super::user::Entity as User;
|
||||
|
|
39
crates/entity/src/sensor_data.rs
Normal file
39
crates/entity/src/sensor_data.rs
Normal file
|
@ -0,0 +1,39 @@
|
|||
//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.1
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)]
|
||||
#[sea_orm(table_name = "sensor_data")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: i32,
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub timestamp: DateTime,
|
||||
#[sea_orm(column_type = "Float")]
|
||||
pub temperature: f32,
|
||||
#[sea_orm(column_type = "Double")]
|
||||
pub voltage: f64,
|
||||
pub uptime: i64,
|
||||
pub node_id: i64,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(
|
||||
belongs_to = "super::node::Entity",
|
||||
from = "Column::NodeId",
|
||||
to = "super::node::Column::Id",
|
||||
on_update = "Cascade",
|
||||
on_delete = "Cascade"
|
||||
)]
|
||||
Node,
|
||||
}
|
||||
|
||||
impl Related<super::node::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Node.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
|
@ -2,6 +2,7 @@ pub use sea_orm_migration::prelude::*;
|
|||
|
||||
mod m20241008_091626_create_table_user;
|
||||
mod m20241008_095058_create_table_node;
|
||||
mod m20241013_134422_create_table_sensor_data;
|
||||
|
||||
pub struct Migrator;
|
||||
|
||||
|
@ -11,6 +12,7 @@ impl MigratorTrait for Migrator {
|
|||
vec![
|
||||
Box::new(m20241008_091626_create_table_user::Migration),
|
||||
Box::new(m20241008_095058_create_table_node::Migration),
|
||||
Box::new(m20241013_134422_create_table_sensor_data::Migration),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,21 +26,11 @@ impl MigrationTrait for Migration {
|
|||
Table::create()
|
||||
.table(Node::Table)
|
||||
.if_not_exists()
|
||||
.col(
|
||||
uuid(Node::Id)
|
||||
.extra("DEFAULT gen_random_uuid()")
|
||||
.primary_key(),
|
||||
)
|
||||
.col(string(Node::Name))
|
||||
.col(boolean(Node::Status).default(false))
|
||||
.col(big_unsigned(Node::Id).primary_key())
|
||||
.col(double(Node::CoordLa))
|
||||
.col(double(Node::CoordLo))
|
||||
.col(float(Node::Temperature).default(-127))
|
||||
.col(double(Node::BatteryMinimum).default(-127))
|
||||
.col(double(Node::BatteryCurrent).default(-127))
|
||||
.col(double(Node::BatteryMaximum).default(-127))
|
||||
.col(double(Node::Voltage).default(-127))
|
||||
.col(big_unsigned(Node::Uptime).default(0))
|
||||
.col(uuid(Node::Group))
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
|
@ -71,25 +61,19 @@ impl MigrationTrait for Migration {
|
|||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum Node {
|
||||
pub enum Node {
|
||||
Table,
|
||||
Id,
|
||||
Name,
|
||||
Status,
|
||||
Id, // Mac address
|
||||
CoordLa,
|
||||
CoordLo,
|
||||
Temperature, // def: -127
|
||||
BatteryMinimum, // def: -127
|
||||
BatteryCurrent, // def: -127
|
||||
BatteryMaximum, // def: -127
|
||||
Voltage, // def: -127
|
||||
Uptime, // def: 0
|
||||
Group,
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum NodeGroup {
|
||||
Table,
|
||||
Id,
|
||||
Name,
|
||||
Id, // Uuid
|
||||
Name, // Groupname
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
use crate::m20241008_095058_create_table_node::Node;
|
||||
use sea_orm_migration::{prelude::*, schema::*};
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
manager
|
||||
.create_table(
|
||||
Table::create()
|
||||
.table(SensorData::Table)
|
||||
.if_not_exists()
|
||||
.col(integer(Node::Id))
|
||||
.col(timestamp(SensorData::Timestamp))
|
||||
.primary_key(
|
||||
Index::create()
|
||||
.col(SensorData::Id)
|
||||
.col(SensorData::Timestamp),
|
||||
)
|
||||
.col(float(SensorData::Temperature).default(-127))
|
||||
.col(double(SensorData::Voltage).default(-127))
|
||||
.col(big_unsigned(SensorData::Uptime).default(0))
|
||||
.col(big_unsigned(SensorData::NodeId))
|
||||
.foreign_key(
|
||||
ForeignKey::create()
|
||||
.name("fk-data-node_id")
|
||||
.from(SensorData::Table, SensorData::NodeId)
|
||||
.to(Node::Table, Node::Id)
|
||||
.on_update(ForeignKeyAction::Cascade)
|
||||
.on_delete(ForeignKeyAction::Cascade),
|
||||
)
|
||||
.to_owned(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||
// Replace the sample below with your own migration scripts
|
||||
|
||||
manager
|
||||
.drop_table(Table::drop().table(SensorData::Table).to_owned())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(DeriveIden)]
|
||||
enum SensorData {
|
||||
Table,
|
||||
Id, // Mac address
|
||||
Timestamp,
|
||||
Temperature, // def: -127
|
||||
Voltage, // def: -127
|
||||
Uptime, // def: 0
|
||||
NodeId,
|
||||
}
|
Loading…
Reference in a new issue