1mod config;
31mod device;
32
33pub use config::ManagerConfig;
34pub use device::Device;
35
36use std::sync::Arc;
37
38use anyhow::{Context, Result};
39
40use crate::{certmanager, controller, transport};
41
42pub struct DeviceManager {
43 base_path: String,
44 config: ManagerConfig,
45 transport: Arc<transport::Transport>,
46 controller: Arc<controller::Controller>,
47 certmanager: Arc<dyn certmanager::CertManager>,
48 registry: std::sync::Mutex<device::DeviceRegistry>,
49}
50
51impl DeviceManager {
52 pub async fn create(base_path: &str, config: ManagerConfig) -> Result<Self> {
55 std::fs::create_dir_all(base_path)
56 .context(format!("creating base directory {}", base_path))?;
57 config::save_config(base_path, &config)?;
58
59 let pem = config::pem_path(base_path);
60 let cm = certmanager::FileCertManager::new(config.fabric_id, &pem);
61 cm.bootstrap()?;
62 cm.create_user(config.controller_id)?;
63
64 let cm: Arc<dyn certmanager::CertManager> = certmanager::FileCertManager::load(&pem)?;
65 let transport = transport::Transport::new(&config.local_address).await?;
66 let controller = controller::Controller::new(&cm, &transport, config.fabric_id)?;
67 let registry = device::DeviceRegistry::load(&config::devices_path(base_path))?;
68
69 Ok(Self {
70 base_path: base_path.to_owned(),
71 config,
72 transport,
73 controller,
74 certmanager: cm,
75 registry: std::sync::Mutex::new(registry),
76 })
77 }
78
79 pub async fn load(base_path: &str) -> Result<Self> {
81 let config = config::load_config(base_path)?;
82 let pem = config::pem_path(base_path);
83 let cm: Arc<dyn certmanager::CertManager> = certmanager::FileCertManager::load(&pem)?;
84 let transport = transport::Transport::new(&config.local_address).await?;
85 let controller = controller::Controller::new(&cm, &transport, config.fabric_id)?;
86 let registry = device::DeviceRegistry::load(&config::devices_path(base_path))?;
87
88 Ok(Self {
89 base_path: base_path.to_owned(),
90 config,
91 transport,
92 controller,
93 certmanager: cm,
94 registry: std::sync::Mutex::new(registry),
95 })
96 }
97
98 pub async fn commission(
101 &self,
102 address: &str,
103 pin: u32,
104 node_id: u64,
105 name: &str,
106 ) -> Result<controller::Connection> {
107 let conn = self.transport.create_connection(address).await;
108 let connection = self
109 .controller
110 .commission(&conn, pin, node_id, self.config.controller_id)
111 .await?;
112
113 let device = Device {
114 node_id,
115 address: address.to_owned(),
116 name: name.to_owned(),
117 };
118 self.registry
119 .lock()
120 .map_err(|e| anyhow::anyhow!("registry lock: {}", e))?
121 .add(device)?;
122
123 Ok(connection)
124 }
125
126 pub async fn connect(&self, node_id: u64) -> Result<controller::Connection> {
128 let address = {
129 let reg = self.registry.lock().map_err(|e| anyhow::anyhow!("registry lock: {}", e))?;
130 reg.get(node_id)
131 .context(format!("device {} not found in registry", node_id))?
132 .address
133 .clone()
134 };
135 let conn = self.transport.create_connection(&address).await;
136 self.controller
137 .auth_sigma(&conn, node_id, self.config.controller_id)
138 .await
139 }
140
141 pub async fn connect_by_name(&self, name: &str) -> Result<controller::Connection> {
143 let (node_id, address) = {
144 let reg = self.registry.lock().map_err(|e| anyhow::anyhow!("registry lock: {}", e))?;
145 let dev = reg
146 .get_by_name(name)
147 .context(format!("device '{}' not found in registry", name))?;
148 (dev.node_id, dev.address.clone())
149 };
150 let conn = self.transport.create_connection(&address).await;
151 self.controller
152 .auth_sigma(&conn, node_id, self.config.controller_id)
153 .await
154 }
155
156 pub fn list_devices(&self) -> Result<Vec<Device>> {
158 let reg = self.registry.lock().map_err(|e| anyhow::anyhow!("registry lock: {}", e))?;
159 Ok(reg.list().to_vec())
160 }
161
162 pub fn get_device(&self, node_id: u64) -> Result<Option<Device>> {
164 let reg = self.registry.lock().map_err(|e| anyhow::anyhow!("registry lock: {}", e))?;
165 Ok(reg.get(node_id).cloned())
166 }
167
168 pub fn get_device_by_name(&self, name: &str) -> Result<Option<Device>> {
170 let reg = self.registry.lock().map_err(|e| anyhow::anyhow!("registry lock: {}", e))?;
171 Ok(reg.get_by_name(name).cloned())
172 }
173
174 pub fn remove_device(&self, node_id: u64) -> Result<()> {
176 self.registry
177 .lock()
178 .map_err(|e| anyhow::anyhow!("registry lock: {}", e))?
179 .remove(node_id)
180 }
181
182 pub fn rename_device(&self, node_id: u64, name: &str) -> Result<()> {
184 self.registry
185 .lock()
186 .map_err(|e| anyhow::anyhow!("registry lock: {}", e))?
187 .rename(node_id, name)
188 }
189
190 pub fn update_device_address(&self, node_id: u64, address: &str) -> Result<()> {
192 self.registry
193 .lock()
194 .map_err(|e| anyhow::anyhow!("registry lock: {}", e))?
195 .update_address(node_id, address)
196 }
197
198 pub fn controller(&self) -> &Arc<controller::Controller> {
200 &self.controller
201 }
202
203 pub fn transport(&self) -> &Arc<transport::Transport> {
205 &self.transport
206 }
207
208 pub fn certmanager(&self) -> &Arc<dyn certmanager::CertManager> {
210 &self.certmanager
211 }
212
213 pub fn config(&self) -> &ManagerConfig {
215 &self.config
216 }
217
218 pub fn base_path(&self) -> &str {
220 &self.base_path
221 }
222}