Skip to main content

alarm_dot_com/models/
lock.rs

1//! Lock model.
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6use super::device::{Device, ResourceType};
7use super::jsonapi::Resource;
8use crate::error::{AlarmError, Result};
9
10/// Lock state.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12pub enum LockState {
13    Unknown,
14    Locked,
15    Unlocked,
16}
17
18impl LockState {
19    pub fn from_code(code: u32) -> Self {
20        match code {
21            1 => LockState::Locked,
22            2 => LockState::Unlocked,
23            _ => LockState::Unknown,
24        }
25    }
26}
27
28impl fmt::Display for LockState {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match self {
31            LockState::Unknown => write!(f, "Unknown"),
32            LockState::Locked => write!(f, "Locked"),
33            LockState::Unlocked => write!(f, "Unlocked"),
34        }
35    }
36}
37
38/// Lock command.
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum LockCommand {
41    Lock,
42    Unlock,
43}
44
45impl LockCommand {
46    pub fn api_action(&self) -> &'static str {
47        match self {
48            LockCommand::Lock => "lock",
49            LockCommand::Unlock => "unlock",
50        }
51    }
52}
53
54/// Lock attributes from the API.
55#[derive(Debug, Clone, Deserialize, Serialize)]
56#[serde(rename_all = "camelCase")]
57pub struct LockAttributes {
58    #[serde(default)]
59    pub state: u32,
60    #[serde(default)]
61    pub desired_state: u32,
62    #[serde(default)]
63    pub description: Option<String>,
64    #[serde(default)]
65    pub has_permission: Option<bool>,
66    #[serde(default)]
67    pub low_battery: Option<bool>,
68    #[serde(default)]
69    pub critical_battery: Option<bool>,
70    #[serde(default)]
71    pub malfunction: Option<bool>,
72}
73
74/// A lock device.
75#[derive(Debug, Clone)]
76pub struct Lock {
77    pub id: String,
78    pub name: String,
79    pub state: LockState,
80    pub desired_state: LockState,
81    pub low_battery: bool,
82    pub malfunction: bool,
83    pub attributes: LockAttributes,
84}
85
86impl Lock {
87    pub fn from_resource(resource: &Resource) -> Result<Self> {
88        let attrs: LockAttributes =
89            serde_json::from_value(resource.attributes.clone()).map_err(|e| {
90                AlarmError::UnexpectedResponse(format!("failed to parse lock attributes: {e}"))
91            })?;
92
93        let name = attrs
94            .description
95            .clone()
96            .unwrap_or_else(|| format!("Lock {}", resource.id));
97
98        Ok(Lock {
99            id: resource.id.clone(),
100            name,
101            state: LockState::from_code(attrs.state),
102            desired_state: LockState::from_code(attrs.desired_state),
103            low_battery: attrs.low_battery.unwrap_or(false),
104            malfunction: attrs.malfunction.unwrap_or(false),
105            attributes: attrs,
106        })
107    }
108}
109
110impl Device for Lock {
111    fn id(&self) -> &str {
112        &self.id
113    }
114
115    fn name(&self) -> &str {
116        &self.name
117    }
118
119    fn resource_type() -> ResourceType {
120        ResourceType::Lock
121    }
122}