1use std::collections::HashMap;
4use std::sync::{Arc};
5use std::time::Duration;
6use futures::{stream, StreamExt};
7use crate::core::{RawButtonPanel, SDCore};
8use crate::core::methods::CoreHandle;
9use hidapi::HidApi;
10use serde_json::Value;
11use tokio::sync::RwLock;
12use tokio::time::sleep;
13use crate::config::{Config, DeviceConfig};
14use crate::{connect, find_decks, ModuleManager, RenderingManager, SocketManager};
15use crate::util::{make_panel_unique};
16
17pub struct CoreManager {
19 hid: RwLock<HidApi>,
20
21 pub config: Arc<Config>,
23
24 devices: RwLock<HashMap<String, DeviceData>>,
25
26 pub module_manager: Arc<ModuleManager>,
28
29 pub render_manager: Arc<RenderingManager>,
31
32 pub socket_manager: Arc<SocketManager>,
34}
35
36#[allow(dead_code)]
37impl CoreManager {
38 pub fn new(module_manager: Arc<ModuleManager>, render_manager: Arc<RenderingManager>, socket_manager: Arc<SocketManager>, config: Arc<Config>) -> Arc<CoreManager> {
40 let hid = HidApi::new().expect("could not connect to hidapi");
41
42 Arc::new(CoreManager {
43 hid: RwLock::new(hid),
44 config,
45 devices: Default::default(),
46 module_manager,
47 render_manager,
48 socket_manager
49 })
50 }
51
52 pub async fn add_devices_from_config(&self) {
54 for config in self.config.get_all_device_configs().await {
55 let config_handle = config.read().await;
56 self.add_device(config_handle.vid, config_handle.pid, &config_handle.serial).await;
57 }
58 }
59
60 pub async fn list_available_devices(&self) -> Vec<(u16, u16, String)> {
62 let mut handle = self.hid.write().await;
63
64 handle.refresh_devices().ok();
65
66 let mut devices = vec![];
67
68 for (vid, pid, serial) in find_decks(&handle) {
69 if let Some(serial) = serial {
70 if !self.is_device_added(&serial).await {
71 devices.push((vid, pid, serial));
72 }
73 }
74 }
75
76 devices
77 }
78
79 pub async fn add_device(&self, vid: u16, pid: u16, serial: &str) {
81 let mut handle = self.devices.write().await;
82
83 if !handle.contains_key(serial) {
84 let data = DeviceData {
85 core: SDCore::blank(self.module_manager.clone(), self.render_manager.clone(), self.socket_manager.clone(), self.config.clone(), Default::default(), Default::default()).await,
86 vid,
87 pid,
88 serial: serial.to_string()
89 };
90
91 self.config.restore_device_config(serial).await;
92
93 handle.insert(serial.to_string(), data.clone());
94 }
95 }
96
97 pub async fn connect_device(&self, vid: u16, pid: u16, serial: &str) -> Result<DeviceData, String> {
99 let hid_handle = self.hid.read().await;
100 let collection = self.config.get_image_collection(serial).await;
101
102 let config = if let Some(config) = self.config.get_device_config(serial).await {
103 config
104 } else {
105 self.config.set_device_config(serial, DeviceConfig {
106 vid,
107 pid,
108 serial: serial.to_string(),
109 brightness: 50,
110 layout: RawButtonPanel {
111 display_name: "Root".to_string(),
112 data: Value::Null,
113 buttons: Default::default()
114 },
115 images: Default::default(),
116 plugin_data: Default::default(),
117 commit_time: Default::default(),
118 dirty_state: false,
119 }).await;
120 self.config.save_device_config(serial).await.ok();
121 self.config.get_device_config(serial).await.unwrap()
122 };
123
124 if let Ok(core) = connect(self.module_manager.clone(), self.render_manager.clone(), self.socket_manager.clone(), self.config.clone(), config.clone(), collection,&hid_handle, vid, pid, serial, self.config.frame_rate()).await {
125 let data = DeviceData {
126 core: core.clone(),
127 vid,
128 pid,
129 serial: serial.to_string()
130 };
131
132 let core_handle = CoreHandle::wrap(core.clone());
133
134 let config_handle = config.read().await;
135
136 let brightness = config_handle.brightness;
137 let layout = config_handle.layout.clone();
138
139 drop(config_handle);
140
141 core_handle.set_brightness(brightness).await;
142 core_handle.reset_stack(make_panel_unique(layout)).await;
143
144
145 let mut handle = self.devices.write().await;
146
147 handle.insert(serial.to_string(), data.clone());
148
149 Ok(data)
150 } else {
151 Err("Failed to connect".to_string())
152 }
153 }
154
155 pub async fn remove_device(&self, serial: &str) {
157 let mut handle = self.devices.write().await;
158 let data = handle.remove(serial);
159
160 if let Some(data) = data {
161 data.core.close().await;
162 self.config.disable_device_config(serial).await;
163 self.config.reload_device_configs().await.ok();
164 }
165 }
166
167 pub async fn list_added_devices(&self) -> HashMap<String, DeviceData> {
169 self.devices.read().await.iter()
170 .map(|(s, d)| (s.clone(), d.clone()))
171 .collect()
172 }
173
174 pub async fn is_device_added(&self, serial: &str) -> bool {
176 self.devices.read().await.contains_key(serial)
177 }
178
179 pub async fn get_device(&self, serial: &str) -> Option<DeviceData> {
181 if let Some(device_data) = self.devices.read().await.get(serial) {
182 if !device_data.core.is_closed().await {
183 Some(device_data.clone())
184 } else {
185 None
186 }
187 } else {
188 None
189 }
190 }
191
192 pub async fn reconnect_routine(&self) {
194 loop {
195 sleep(Duration::from_secs_f32(self.config.reconnect_rate())).await;
196
197 let disconnected = self.get_disconnected().await;
198
199 if !disconnected.is_empty() {
200 for (serial, device) in disconnected {
201 log::warn!("{} is disconnected, attempting to reconnect", serial);
202 if let Ok(_) = self.connect_device(device.vid, device.pid, &device.serial).await {
203 log::info!("Reconnected {}", serial);
204 }
205 }
206 }
207 }
208 }
209
210 async fn get_disconnected(&self) -> HashMap<String, DeviceData> {
212 let handle = self.devices.read().await;
213
214 let map = stream::iter(handle.iter())
215 .filter(|(_, d)| async { d.core.is_closed().await })
216 .map(|(s, d)| (s.clone(), d.clone()))
217 .collect().await;
218
219 drop(handle);
220
221 map
222 }
223}
224
225#[derive(Clone)]
227pub struct DeviceData {
228 pub core: Arc<SDCore>,
230 pub vid: u16,
232 pub pid: u16,
234 pub serial: String,
236}