use native_db::{native_db, ToKey};
use native_model::{native_model, Model};
use serde::{Deserialize, Serialize};
pub use super::v1::{
Action, AncestorLocal, Device, DevicePrettyLocation, DeviceType, EntityLifecycle, Heartbeat,
Herd, Layer, MediaType, Plan, PlanInsert, PlanType, ResponseScout, ResponseScoutStatus,
Syncable, TagObservationType, Zone,
};
pub use super::v2::{Operator, OperatorLocal};
pub use super::v6::{Connectivity, ConnectivityLocal, Tag};
pub use super::v8::TagLocal;
fn lifecycle_defaults() -> (
super::v1::EntityLifecycle,
String,
Option<String>,
Option<String>,
) {
use chrono::Utc;
(
super::v1::EntityLifecycle::Active,
Utc::now().to_rfc3339(),
None,
None,
)
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[native_model(id = 14, version = 2)]
#[native_db]
pub struct SessionLocal {
pub id: Option<i64>,
#[primary_key]
pub id_local: Option<String>,
pub device_id: i64,
pub timestamp_start: String,
pub timestamp_end: Option<String>,
pub inserted_at: Option<String>,
pub software_version: String,
pub locations: Option<String>,
pub altitude_max: f64,
pub altitude_min: f64,
pub altitude_average: f64,
pub velocity_max: f64,
pub velocity_min: f64,
pub velocity_average: f64,
pub distance_total: f64,
pub distance_max_from_start: f64,
pub battery_id: Option<i64>,
pub post_approver: Option<String>,
#[serde(default)]
pub lifecycle: EntityLifecycle,
pub lifecycle_changed_at: String,
#[serde(default)]
pub lifecycle_changed_by: Option<String>,
#[serde(default)]
pub lifecycle_reason: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionStatus {
InProgress,
Finalized,
Interrupted,
Cancelled,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SessionEndReason {
Completed,
Superseded,
ReportingLost,
InactivityTimeout,
OperatorCancelled,
SystemCancelled,
Other,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Session {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
pub device_id: i64,
pub timestamp_start: String,
pub timestamp_end: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub inserted_at: Option<String>,
pub software_version: String,
pub locations: Option<String>,
pub altitude_max: f64,
pub altitude_min: f64,
pub altitude_average: f64,
pub velocity_max: f64,
pub velocity_min: f64,
pub velocity_average: f64,
pub distance_total: f64,
pub distance_max_from_start: f64,
#[serde(skip_serializing_if = "Option::is_none")]
pub battery_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub secondary_battery_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub post_approver: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_approver: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_approver: Option<String>,
#[serde(default)]
pub lifecycle: EntityLifecycle,
#[serde(skip_serializing_if = "Option::is_none")]
pub lifecycle_changed_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lifecycle_changed_by: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lifecycle_reason: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<SessionStatus>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub end_reason: Option<SessionEndReason>,
}
impl Default for SessionLocal {
fn default() -> Self {
Self {
id: None,
id_local: None,
device_id: 0,
timestamp_start: String::new(),
timestamp_end: None,
inserted_at: None,
software_version: String::new(),
locations: None,
altitude_max: 0.0,
altitude_min: 0.0,
altitude_average: 0.0,
velocity_max: 0.0,
velocity_min: 0.0,
velocity_average: 0.0,
distance_total: 0.0,
distance_max_from_start: 0.0,
battery_id: None,
post_approver: None,
lifecycle: EntityLifecycle::Active,
lifecycle_changed_at: chrono::Utc::now().to_rfc3339(),
lifecycle_changed_by: None,
lifecycle_reason: None,
}
}
}
impl Default for Session {
fn default() -> Self {
Self {
id: None,
device_id: 0,
timestamp_start: String::new(),
timestamp_end: None,
inserted_at: None,
software_version: String::new(),
locations: None,
altitude_max: 0.0,
altitude_min: 0.0,
altitude_average: 0.0,
velocity_max: 0.0,
velocity_min: 0.0,
velocity_average: 0.0,
distance_total: 0.0,
distance_max_from_start: 0.0,
battery_id: None,
secondary_battery_id: None,
post_approver: None,
start_approver: None,
end_approver: None,
lifecycle: EntityLifecycle::Active,
lifecycle_changed_at: None,
lifecycle_changed_by: None,
lifecycle_reason: None,
status: Some(SessionStatus::InProgress),
end_reason: None,
}
}
}
impl Syncable for SessionLocal {
fn id(&self) -> Option<i64> {
self.id
}
fn set_id(&mut self, id: i64) {
self.id = Some(id);
}
fn id_local(&self) -> Option<String> {
self.id_local.clone()
}
fn set_id_local(&mut self, id_local: String) {
self.id_local = Some(id_local);
}
}
impl Syncable for Session {
fn id(&self) -> Option<i64> {
self.id
}
fn set_id(&mut self, id: i64) {
self.id = Some(id);
}
fn id_local(&self) -> Option<String> {
None }
fn set_id_local(&mut self, _id_local: String) {
}
}
impl From<SessionLocal> for Session {
fn from(local: SessionLocal) -> Self {
Session {
id: local.id,
device_id: local.device_id,
timestamp_start: local.timestamp_start,
timestamp_end: local.timestamp_end,
inserted_at: local.inserted_at,
software_version: local.software_version,
locations: local.locations,
altitude_max: local.altitude_max,
altitude_min: local.altitude_min,
altitude_average: local.altitude_average,
velocity_max: local.velocity_max,
velocity_min: local.velocity_min,
velocity_average: local.velocity_average,
distance_total: local.distance_total,
distance_max_from_start: local.distance_max_from_start,
battery_id: local.battery_id,
secondary_battery_id: None,
post_approver: local.post_approver,
start_approver: None,
end_approver: None,
lifecycle: local.lifecycle,
lifecycle_changed_at: Some(local.lifecycle_changed_at.clone()),
lifecycle_changed_by: local.lifecycle_changed_by.clone(),
lifecycle_reason: local.lifecycle_reason.clone(),
status: None,
end_reason: None,
}
}
}
impl From<Session> for SessionLocal {
fn from(session: Session) -> Self {
SessionLocal {
id: session.id,
id_local: None, device_id: session.device_id,
timestamp_start: session.timestamp_start,
timestamp_end: session.timestamp_end,
inserted_at: session.inserted_at,
software_version: session.software_version,
locations: session.locations,
altitude_max: session.altitude_max,
altitude_min: session.altitude_min,
altitude_average: session.altitude_average,
velocity_max: session.velocity_max,
velocity_min: session.velocity_min,
velocity_average: session.velocity_average,
distance_total: session.distance_total,
distance_max_from_start: session.distance_max_from_start,
battery_id: session.battery_id,
post_approver: session.post_approver,
lifecycle: session.lifecycle,
lifecycle_changed_at: session
.lifecycle_changed_at
.clone()
.unwrap_or_else(|| chrono::Utc::now().to_rfc3339()),
lifecycle_changed_by: session.lifecycle_changed_by,
lifecycle_reason: session.lifecycle_reason,
}
}
}
impl From<super::v1::SessionLocal> for SessionLocal {
fn from(v1: super::v1::SessionLocal) -> Self {
let (lifecycle, default_changed_at, lifecycle_changed_by, lifecycle_reason) =
lifecycle_defaults();
let lifecycle_changed_at = v1.inserted_at.clone().unwrap_or(default_changed_at);
Self {
id: v1.id,
id_local: v1.id_local,
device_id: v1.device_id,
timestamp_start: v1.timestamp_start,
timestamp_end: v1.timestamp_end,
inserted_at: v1.inserted_at,
software_version: v1.software_version,
locations: v1.locations,
altitude_max: v1.altitude_max,
altitude_min: v1.altitude_min,
altitude_average: v1.altitude_average,
velocity_max: v1.velocity_max,
velocity_min: v1.velocity_min,
velocity_average: v1.velocity_average,
distance_total: v1.distance_total,
distance_max_from_start: v1.distance_max_from_start,
battery_id: v1.battery_id,
post_approver: v1.post_approver,
lifecycle,
lifecycle_changed_at,
lifecycle_changed_by,
lifecycle_reason,
}
}
}
impl Session {
pub fn new(
device_id: i64,
timestamp_start: u64,
timestamp_end: Option<u64>,
software_version: String,
location: Option<String>,
altitude_max: f64,
altitude_min: f64,
altitude_average: f64,
velocity_max: f64,
velocity_min: f64,
velocity_average: f64,
distance_total: f64,
distance_max_from_start: f64,
) -> Self {
use chrono::{DateTime, Utc};
let (lifecycle, lifecycle_changed_at, lifecycle_changed_by, lifecycle_reason) =
lifecycle_defaults();
let timestamp_start_str = DateTime::from_timestamp(timestamp_start as i64, 0)
.unwrap_or_else(|| DateTime::<Utc>::from_timestamp(0, 0).unwrap())
.to_rfc3339();
let timestamp_end_str = timestamp_end.map(|t| {
DateTime::from_timestamp(t as i64, 0)
.unwrap_or_else(|| DateTime::<Utc>::from_timestamp(0, 0).unwrap())
.to_rfc3339()
});
Self {
id: None,
device_id,
timestamp_start: timestamp_start_str,
timestamp_end: timestamp_end_str,
inserted_at: None,
software_version,
locations: location,
altitude_max,
altitude_min,
altitude_average,
velocity_max,
velocity_min,
velocity_average,
distance_total,
distance_max_from_start,
battery_id: None,
secondary_battery_id: None,
post_approver: None,
start_approver: None,
end_approver: None,
lifecycle,
lifecycle_changed_at: Some(lifecycle_changed_at),
lifecycle_changed_by,
lifecycle_reason,
status: Some(SessionStatus::InProgress),
end_reason: None,
}
}
pub fn update_timestamp_end(&mut self, timestamp_end: u64) {
use chrono::{DateTime, Utc};
self.timestamp_end = Some(
DateTime::from_timestamp(timestamp_end as i64, 0)
.unwrap_or_else(|| DateTime::<Utc>::from_timestamp(0, 0).unwrap())
.to_rfc3339(),
);
}
pub fn end(&mut self, timestamp_end: u64, status: SessionStatus, end_reason: SessionEndReason) {
self.update_timestamp_end(timestamp_end);
self.status = Some(status);
self.end_reason = Some(end_reason);
}
}
impl SessionLocal {
pub fn update_timestamp_end(&mut self, timestamp_end: u64) {
use chrono::{DateTime, Utc};
self.timestamp_end = Some(
DateTime::from_timestamp(timestamp_end as i64, 0)
.unwrap_or_else(|| DateTime::<Utc>::from_timestamp(0, 0).unwrap())
.to_rfc3339(),
);
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[native_model(id = 19, version = 8)]
#[native_db]
pub struct ArtifactLocal {
pub id: Option<i64>,
#[primary_key]
pub id_local: Option<String>,
#[secondary_key]
pub ancestor_id_local: Option<String>,
pub created_at: Option<String>,
pub file_path: String,
#[secondary_key]
pub session_id: Option<i64>,
pub timestamp_observation: Option<String>,
pub modality: Option<String>,
pub device_id: i64,
pub updated_at: Option<String>,
pub timestamp_observation_end: String,
pub has_uploaded_file_to_storage: bool,
pub upload_url: Option<String>,
pub upload_url_generated_at: Option<String>,
pub file_size_bytes: Option<i64>,
pub tagged_at: Option<String>,
pub embedded_at: Option<String>,
pub segmented_at: Option<String>,
pub tracked_at: Option<String>,
#[serde(default)]
pub lifecycle: EntityLifecycle,
pub lifecycle_changed_at: String,
#[serde(default)]
pub lifecycle_changed_by: Option<String>,
#[serde(default)]
pub lifecycle_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Artifact {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
pub file_path: String,
pub session_id: Option<i64>,
pub timestamp_observation: Option<String>,
pub modality: Option<String>,
pub device_id: i64,
pub updated_at: Option<String>,
pub timestamp_observation_end: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_size_bytes: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tagged_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedded_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub segmented_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tracked_at: Option<String>,
#[serde(default)]
pub lifecycle: EntityLifecycle,
#[serde(skip_serializing_if = "Option::is_none")]
pub lifecycle_changed_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lifecycle_changed_by: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lifecycle_reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SegmentationSam3 {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub artifact_id: Option<i64>,
#[serde(default)]
pub frame_index: i64,
pub mask_rle: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub conf: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_location: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_pitch: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_heading: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_roll: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sensor_pitch: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sensor_yaw: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sensor_roll: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_height: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp_observation: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject_location: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject_height: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject_id: Option<i64>,
}
impl Default for ArtifactLocal {
fn default() -> Self {
use chrono::Utc;
Self {
id: None,
id_local: None,
ancestor_id_local: None,
created_at: None,
file_path: String::new(),
session_id: None,
timestamp_observation: None,
modality: None,
device_id: 0,
updated_at: None,
timestamp_observation_end: Utc::now().to_rfc3339(),
has_uploaded_file_to_storage: false,
upload_url: None,
upload_url_generated_at: None,
file_size_bytes: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
lifecycle: EntityLifecycle::Active,
lifecycle_changed_at: chrono::Utc::now().to_rfc3339(),
lifecycle_changed_by: None,
lifecycle_reason: None,
}
}
}
impl super::v1::Syncable for ArtifactLocal {
fn id(&self) -> Option<i64> {
self.id
}
fn set_id(&mut self, id: i64) {
self.id = Some(id);
}
fn id_local(&self) -> Option<String> {
self.id_local.clone()
}
fn set_id_local(&mut self, id_local: String) {
self.id_local = Some(id_local);
}
}
impl super::v1::AncestorLocal for ArtifactLocal {
fn ancestor_id_local(&self) -> Option<String> {
self.ancestor_id_local.clone()
}
fn set_ancestor_id_local(&mut self, ancestor_id_local: String) {
self.ancestor_id_local = Some(ancestor_id_local);
}
}
impl From<ArtifactLocal> for Artifact {
fn from(local: ArtifactLocal) -> Self {
Self {
id: local.id,
created_at: local.created_at,
file_path: local.file_path,
session_id: local.session_id,
timestamp_observation: local.timestamp_observation,
modality: local.modality,
device_id: local.device_id,
updated_at: local.updated_at,
timestamp_observation_end: local.timestamp_observation_end,
file_size_bytes: local.file_size_bytes,
tagged_at: local.tagged_at,
embedded_at: local.embedded_at,
segmented_at: local.segmented_at,
tracked_at: local.tracked_at,
lifecycle: local.lifecycle,
lifecycle_changed_at: Some(local.lifecycle_changed_at.clone()),
lifecycle_changed_by: local.lifecycle_changed_by.clone(),
lifecycle_reason: local.lifecycle_reason.clone(),
}
}
}
impl From<Artifact> for ArtifactLocal {
fn from(a: Artifact) -> Self {
Self {
id: a.id,
id_local: None,
ancestor_id_local: None,
created_at: a.created_at,
file_path: a.file_path,
session_id: a.session_id,
timestamp_observation: a.timestamp_observation,
modality: a.modality,
device_id: a.device_id,
updated_at: a.updated_at,
timestamp_observation_end: a.timestamp_observation_end,
has_uploaded_file_to_storage: false,
upload_url: None,
upload_url_generated_at: None,
file_size_bytes: a.file_size_bytes,
tagged_at: a.tagged_at,
embedded_at: a.embedded_at,
segmented_at: a.segmented_at,
tracked_at: a.tracked_at,
lifecycle: a.lifecycle,
lifecycle_changed_at: a
.lifecycle_changed_at
.clone()
.unwrap_or_else(|| chrono::Utc::now().to_rfc3339()),
lifecycle_changed_by: a.lifecycle_changed_by,
lifecycle_reason: a.lifecycle_reason,
}
}
}
impl From<super::v7::ArtifactLocal> for ArtifactLocal {
fn from(v7: super::v7::ArtifactLocal) -> Self {
let (lifecycle, lifecycle_changed_at, lifecycle_changed_by, lifecycle_reason) =
lifecycle_defaults();
Self {
id: v7.id,
id_local: v7.id_local,
ancestor_id_local: v7.ancestor_id_local,
created_at: v7.created_at,
file_path: v7.file_path,
session_id: v7.session_id,
timestamp_observation: v7.timestamp_observation,
modality: v7.modality,
device_id: v7.device_id,
updated_at: v7.updated_at,
timestamp_observation_end: v7.timestamp_observation_end,
has_uploaded_file_to_storage: v7.has_uploaded_file_to_storage,
upload_url: v7.upload_url,
upload_url_generated_at: v7.upload_url_generated_at,
file_size_bytes: v7.file_size_bytes,
tagged_at: v7.tagged_at,
embedded_at: v7.embedded_at,
segmented_at: v7.segmented_at,
tracked_at: v7.tracked_at,
lifecycle,
lifecycle_changed_at,
lifecycle_changed_by,
lifecycle_reason,
}
}
}
impl From<super::v6::ArtifactLocal> for ArtifactLocal {
fn from(v6: super::v6::ArtifactLocal) -> Self {
let (lifecycle, lifecycle_changed_at, lifecycle_changed_by, lifecycle_reason) =
lifecycle_defaults();
Self {
id: v6.id,
id_local: v6.id_local,
ancestor_id_local: v6.ancestor_id_local,
created_at: v6.created_at,
file_path: v6.file_path,
session_id: v6.session_id,
timestamp_observation: v6.timestamp_observation,
modality: v6.modality,
device_id: v6.device_id,
updated_at: v6.updated_at,
timestamp_observation_end: v6.timestamp_observation_end,
has_uploaded_file_to_storage: v6.has_uploaded_file_to_storage,
upload_url: v6.upload_url,
upload_url_generated_at: v6.upload_url_generated_at,
file_size_bytes: v6.file_size_bytes,
tagged_at: v6.tagged_at,
embedded_at: None,
segmented_at: None,
tracked_at: None,
lifecycle,
lifecycle_changed_at,
lifecycle_changed_by,
lifecycle_reason,
}
}
}
impl From<super::v6::Artifact> for Artifact {
fn from(v6: super::v6::Artifact) -> Self {
let (lifecycle, lifecycle_changed_at, lifecycle_changed_by, lifecycle_reason) =
lifecycle_defaults();
Self {
id: v6.id,
created_at: v6.created_at,
file_path: v6.file_path,
session_id: v6.session_id,
timestamp_observation: v6.timestamp_observation,
modality: v6.modality,
device_id: v6.device_id,
updated_at: v6.updated_at,
timestamp_observation_end: v6.timestamp_observation_end,
file_size_bytes: v6.file_size_bytes,
tagged_at: v6.tagged_at,
embedded_at: None,
segmented_at: None,
tracked_at: None,
lifecycle,
lifecycle_changed_at: Some(lifecycle_changed_at),
lifecycle_changed_by,
lifecycle_reason,
}
}
}
impl Artifact {
pub fn new(
file_path: String,
session_id: Option<i64>,
device_id: i64,
modality: Option<String>,
timestamp_observation: Option<String>,
) -> Self {
use chrono::Utc;
Self {
id: None,
created_at: None,
file_path,
session_id,
timestamp_observation,
modality,
device_id,
updated_at: None,
timestamp_observation_end: Utc::now().to_rfc3339(),
file_size_bytes: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
lifecycle: EntityLifecycle::Active,
lifecycle_changed_at: Some(chrono::Utc::now().to_rfc3339()),
lifecycle_changed_by: None,
lifecycle_reason: None,
}
}
}
impl ArtifactLocal {
pub fn new(
file_path: String,
session_id: Option<i64>,
device_id: i64,
modality: Option<String>,
timestamp_observation: Option<String>,
) -> Self {
use chrono::Utc;
Self {
id: None,
id_local: None,
ancestor_id_local: None,
created_at: None,
file_path,
session_id,
timestamp_observation,
modality,
device_id,
updated_at: None,
timestamp_observation_end: Utc::now().to_rfc3339(),
has_uploaded_file_to_storage: false,
upload_url: None,
upload_url_generated_at: None,
file_size_bytes: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
lifecycle: EntityLifecycle::Active,
lifecycle_changed_at: chrono::Utc::now().to_rfc3339(),
lifecycle_changed_by: None,
lifecycle_reason: None,
}
}
pub fn mark_file_uploaded(&mut self) {
self.has_uploaded_file_to_storage = true;
}
pub fn mark_file_not_uploaded(&mut self) {
self.has_uploaded_file_to_storage = false;
}
pub fn is_file_uploaded(&self) -> bool {
self.has_uploaded_file_to_storage
}
pub fn needs_file_upload(&self) -> bool {
!self.has_uploaded_file_to_storage
}
}