fundamentum_sdk_api/client/
provisioning_api.rs

1//! "Provisioning" section in [Fundamentum API](https://dimonoff.atlassian.net/wiki/spaces/F2/pages/306273353781/Devices+API).
2
3use std::marker::PhantomData;
4
5use super::{
6    api_version::{V2, V3},
7    errors::SdkClientError,
8    sdk_client::SdkClient,
9};
10use crate::models::{
11    constants::{DEFAULT_ASSET_TYPE_ID, PROVISIONING_PATH},
12    provisioning::{ProvisionReqV2, ProvisionReqV3, ProvisionRes},
13};
14
15/// Project identification.
16#[derive(Debug, Clone)]
17pub struct ProvisioningApiConfig {
18    /// Project id on the Hub.
19    pub project_id: u32,
20    /// Region id on the Hub.
21    pub region_id: u32,
22    /// Registry id on the Hub.
23    pub registry_id: u32,
24    /// Access token.
25    pub access_token: String,
26}
27
28/// Provisioning section of the devices API.
29pub struct ProvisioningApi<'a, V> {
30    client: &'a SdkClient,
31    api_config: &'a ProvisioningApiConfig,
32
33    // We use PhantomData to make the compiler think that we are using the V type.
34    // Read more here: <https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns>
35    _marker: PhantomData<fn() -> V>,
36}
37
38impl<'a, V> ProvisioningApi<'a, V> {
39    /// Create a new interface for the Provisioning API.
40    #[must_use]
41    pub fn new(client: &'a SdkClient, api_config: &'a ProvisioningApiConfig) -> Self {
42        Self {
43            client,
44            api_config,
45            _marker: PhantomData,
46        }
47    }
48}
49
50impl ProvisioningApi<'_, V2> {
51    /// Provision a new device using the V2 API.
52    ///
53    /// # Errors
54    ///
55    /// An error may occur while sending the request or by the API ([link]()).
56    pub async fn provision(
57        &self,
58        serial_number: impl Into<String> + Send,
59        public_key: impl Into<String> + Send,
60        asset_type: Option<i32>,
61    ) -> Result<ProvisionRes, SdkClientError> {
62        let body = ProvisionReqV2 {
63            project_id: self.api_config.project_id,
64            region_id: self.api_config.region_id,
65            registry_id: self.api_config.registry_id,
66            serial_number: serial_number.into(),
67            access_token: self.api_config.access_token.clone(),
68            public_key: public_key.into(),
69            asset_type_id: asset_type.unwrap_or(DEFAULT_ASSET_TYPE_ID),
70        };
71
72        self.client.post_body(PROVISIONING_PATH, body).await
73    }
74}
75
76impl ProvisioningApi<'_, V3> {
77    /// Provision a new device using the V3 API.
78    ///
79    /// # Errors
80    ///
81    /// An error may occur while sending the request or by the API ([link]()).
82    pub async fn provision(
83        &self,
84        serial_number: impl Into<String> + Send,
85        public_key: impl Into<String> + Send,
86        asset_type: Option<i32>,
87        replace: bool,
88    ) -> Result<ProvisionRes, SdkClientError> {
89        let body = ProvisionReqV3 {
90            project_id: self.api_config.project_id,
91            region_id: self.api_config.region_id,
92            registry_id: self.api_config.registry_id,
93            serial_number: serial_number.into(),
94            access_token: self.api_config.access_token.clone(),
95            secret: public_key.into(),
96            asset_type_id: asset_type.unwrap_or(DEFAULT_ASSET_TYPE_ID),
97        };
98
99        if replace {
100            self.client.put_body(PROVISIONING_PATH, body).await
101        } else {
102            self.client.post_body(PROVISIONING_PATH, body).await
103        }
104    }
105}