ring_client/client/api/
device.rs

1use crate::client::api::error::ApiError;
2use crate::client::api::RingApi;
3use crate::client::authentication::Tokens;
4use crate::helper;
5use crate::helper::url::Url;
6use serde::Deserialize;
7use serde_json::Value;
8use std::collections::HashMap;
9use std::fmt;
10use std::fmt::{Debug, Formatter};
11
12/// Data about a device in a Ring account.
13#[derive(Deserialize, Debug)]
14#[serde(tag = "kind")]
15#[serde(rename_all = "snake_case")]
16pub enum DeviceData {
17    /// A Ring Security Camera.
18    ///
19    /// For example, a [Stick Up Camera](https://en-uk.ring.com/products/stick-up-security-camera-plugin).
20    CocoaCamera {
21        /// The ID of the device.
22        id: usize,
23
24        /// The ID of the location the device is in.
25        ///
26        /// See [`crate::location::Location`]
27        location_id: String,
28
29        /// The description of the device.
30        description: String,
31
32        #[serde(flatten)]
33        #[allow(missing_docs)]
34        extra: HashMap<String, Value>,
35    },
36    /// A Ring Doorbell.
37    ///
38    /// For example, a [Video Doorbell Pro 2](https://en-uk.ring.com/products/video-doorbell-pro-2).
39    DoorbellGrahamCracker {
40        /// The ID of the device.
41        id: usize,
42
43        /// The ID of the location the device is in.
44        location_id: String,
45
46        /// The description of the device.
47        description: String,
48
49        #[serde(flatten)]
50        #[allow(missing_docs)]
51        extra: HashMap<String, Value>,
52    },
53    /// A Ring Alarm Base Station.
54    ///
55    /// They are available as part of the [Alarm Pack](https://en-uk.ring.com/products/alarm-security-5-piece-kit-gen-2).
56    BaseStationV1 {
57        /// The ID of the device.
58        id: usize,
59
60        /// The ID of the location the device is in.
61        location_id: String,
62
63        /// The description of the device.
64        description: String,
65
66        #[serde(flatten)]
67        #[allow(missing_docs)]
68        extra: HashMap<String, Value>,
69    },
70
71    /// A device which is yet to be mapped by the crate.
72    #[serde(other)]
73    Other,
74}
75
76/// A Device which is enabled in a Ring account.
77pub struct Device {
78    #[allow(missing_docs)]
79    pub data: DeviceData,
80}
81
82impl Debug for Device {
83    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
84        f.debug_struct("Device").field("data", &self.data).finish()
85    }
86}
87
88impl Device {
89    pub(crate) const fn new(data: DeviceData) -> Self {
90        Self { data }
91    }
92}
93
94#[derive(Deserialize)]
95struct Response {
96    doorbots: Vec<DeviceData>,
97    authorized_doorbots: Vec<DeviceData>,
98    chimes: Vec<DeviceData>,
99    stickup_cams: Vec<DeviceData>,
100    base_stations: Vec<DeviceData>,
101    beams: Vec<DeviceData>,
102    beams_bridges: Vec<DeviceData>,
103    other: Vec<DeviceData>,
104}
105
106impl RingApi {
107    pub async fn get_device_data(&self, tokens: &Tokens) -> Result<Vec<DeviceData>, ApiError> {
108        let response = self
109            .client
110            .get(helper::url::get_base_url(&Url::Devices))
111            .header("User-Agent", self.operating_system.get_user_agent())
112            .bearer_auth(&tokens.access_token)
113            .send()
114            .await?
115            .json::<Response>()
116            .await?;
117
118        Ok(Vec::new()
119            .into_iter()
120            .chain(response.doorbots)
121            .chain(response.authorized_doorbots)
122            .chain(response.chimes)
123            .chain(response.stickup_cams)
124            .chain(response.base_stations)
125            .chain(response.beams)
126            .chain(response.beams_bridges)
127            .chain(response.other)
128            .collect())
129    }
130}