1pub fn format_error_with_guidance(error: &str) -> (String, Option<String>) {
10 let error_lower = error.to_lowercase();
11
12 if error_lower.contains("characteristic not found") {
14 return (
15 "Device communication error".to_string(),
16 Some("The device may need a firmware update or may be incompatible.".to_string()),
17 );
18 }
19
20 if error_lower.contains("not found") || error_lower.contains("no devices") {
22 return (
23 "Device not found".to_string(),
24 Some(
25 "Make sure the device is powered on, in range, and not connected to another app."
26 .to_string(),
27 ),
28 );
29 }
30
31 if error_lower.contains("no bluetooth adapter") || error_lower.contains("adapter unavailable") {
33 return (
34 "Bluetooth unavailable".to_string(),
35 Some("Check that Bluetooth is enabled in System Settings.".to_string()),
36 );
37 }
38
39 if error_lower.contains("timed out") || error_lower.contains("timeout") {
41 return (
42 "Connection timed out".to_string(),
43 Some("Move closer to the device or try again. The device may be busy.".to_string()),
44 );
45 }
46
47 if error_lower.contains("already connected") {
49 return (
50 "Device busy".to_string(),
51 Some("The device may be connected to another app. Close other Bluetooth apps and try again.".to_string()),
52 );
53 }
54
55 if error_lower.contains("permission") || error_lower.contains("access denied") {
57 return (
58 "Bluetooth permission denied".to_string(),
59 Some(
60 "Grant Bluetooth permissions in System Settings > Privacy & Security.".to_string(),
61 ),
62 );
63 }
64
65 if error_lower.contains("rejected") || error_lower.contains("pairing") {
67 return (
68 "Connection rejected".to_string(),
69 Some("Try removing the device from Bluetooth settings and reconnecting.".to_string()),
70 );
71 }
72
73 if error_lower.contains("out of range") {
75 return (
76 "Device out of range".to_string(),
77 Some(
78 "Move closer to the device (within 10 meters with clear line of sight)."
79 .to_string(),
80 ),
81 );
82 }
83
84 if error_lower.contains("invalid reading") || error_lower.contains("invalid data") {
86 return (
87 "Invalid sensor data".to_string(),
88 Some(
89 "The device returned unexpected data. Try refreshing or reconnecting.".to_string(),
90 ),
91 );
92 }
93
94 if error_lower.contains("bluetooth error") || error_lower.contains("ble error") {
96 return (
97 "Bluetooth error".to_string(),
98 Some(
99 "Try disabling and re-enabling Bluetooth, or restart the application.".to_string(),
100 ),
101 );
102 }
103
104 (error.to_string(), None)
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_device_not_found() {
114 let (msg, suggestion) = format_error_with_guidance("Device 'Aranet4 12345' not found");
115 assert_eq!(msg, "Device not found");
116 assert!(suggestion.is_some());
117 assert!(suggestion.unwrap().contains("powered on"));
118 }
119
120 #[test]
121 fn test_no_devices() {
122 let (msg, suggestion) = format_error_with_guidance("No devices available in range");
123 assert_eq!(msg, "Device not found");
124 assert!(suggestion.is_some());
125 }
126
127 #[test]
128 fn test_timeout() {
129 let (msg, suggestion) = format_error_with_guidance("Connection timed out after 30s");
130 assert_eq!(msg, "Connection timed out");
131 assert!(suggestion.is_some());
132 }
133
134 #[test]
135 fn test_timeout_variant() {
136 let (msg, suggestion) = format_error_with_guidance("Operation timeout");
137 assert_eq!(msg, "Connection timed out");
138 assert!(suggestion.unwrap().contains("Move closer"));
139 }
140
141 #[test]
142 fn test_no_bluetooth_adapter() {
143 let (msg, suggestion) = format_error_with_guidance("No Bluetooth adapter available");
144 assert_eq!(msg, "Bluetooth unavailable");
145 assert!(suggestion.is_some());
146 assert!(suggestion.unwrap().contains("System Settings"));
147 }
148
149 #[test]
150 fn test_adapter_unavailable() {
151 let (msg, suggestion) = format_error_with_guidance("Bluetooth adapter unavailable");
152 assert_eq!(msg, "Bluetooth unavailable");
153 assert!(suggestion.is_some());
154 }
155
156 #[test]
157 fn test_device_already_connected() {
158 let (msg, suggestion) = format_error_with_guidance("Device is already connected");
159 assert_eq!(msg, "Device busy");
160 assert!(suggestion.is_some());
161 assert!(suggestion.unwrap().contains("other Bluetooth apps"));
162 }
163
164 #[test]
165 fn test_permission_denied() {
166 let (msg, suggestion) = format_error_with_guidance("Bluetooth permission denied");
167 assert_eq!(msg, "Bluetooth permission denied");
168 assert!(suggestion.is_some());
169 assert!(suggestion.unwrap().contains("Privacy & Security"));
170 }
171
172 #[test]
173 fn test_access_denied() {
174 let (msg, suggestion) = format_error_with_guidance("Access denied to Bluetooth");
175 assert_eq!(msg, "Bluetooth permission denied");
176 assert!(suggestion.is_some());
177 }
178
179 #[test]
180 fn test_connection_rejected() {
181 let (msg, suggestion) = format_error_with_guidance("Connection rejected by device");
182 assert_eq!(msg, "Connection rejected");
183 assert!(suggestion.is_some());
184 assert!(suggestion.unwrap().contains("removing the device"));
185 }
186
187 #[test]
188 fn test_pairing_failed() {
189 let (msg, suggestion) = format_error_with_guidance("Pairing failed with device");
190 assert_eq!(msg, "Connection rejected");
191 assert!(suggestion.is_some());
192 }
193
194 #[test]
195 fn test_out_of_range() {
196 let (msg, suggestion) = format_error_with_guidance("Device is out of range");
197 assert_eq!(msg, "Device out of range");
198 assert!(suggestion.is_some());
199 assert!(suggestion.unwrap().contains("10 meters"));
200 }
201
202 #[test]
203 fn test_characteristic_not_found() {
204 let (msg, suggestion) = format_error_with_guidance("Characteristic not found on device");
205 assert_eq!(msg, "Device communication error");
206 assert!(suggestion.is_some());
207 assert!(suggestion.unwrap().contains("firmware update"));
208 }
209
210 #[test]
211 fn test_invalid_reading() {
212 let (msg, suggestion) = format_error_with_guidance("Invalid reading received from sensor");
213 assert_eq!(msg, "Invalid sensor data");
214 assert!(suggestion.is_some());
215 assert!(suggestion.unwrap().contains("reconnecting"));
216 }
217
218 #[test]
219 fn test_invalid_data() {
220 let (msg, suggestion) = format_error_with_guidance("Invalid data format");
221 assert_eq!(msg, "Invalid sensor data");
222 assert!(suggestion.is_some());
223 }
224
225 #[test]
226 fn test_generic_bluetooth_error() {
227 let (msg, suggestion) = format_error_with_guidance("Bluetooth error occurred");
228 assert_eq!(msg, "Bluetooth error");
229 assert!(suggestion.is_some());
230 assert!(suggestion.unwrap().contains("re-enabling Bluetooth"));
231 }
232
233 #[test]
234 fn test_generic_ble_error() {
235 let (msg, suggestion) = format_error_with_guidance("BLE error: connection failed");
236 assert_eq!(msg, "Bluetooth error");
237 assert!(suggestion.is_some());
238 }
239
240 #[test]
241 fn test_unknown_error() {
242 let (msg, suggestion) = format_error_with_guidance("Some random error xyz");
243 assert_eq!(msg, "Some random error xyz");
244 assert!(suggestion.is_none());
245 }
246
247 #[test]
248 fn test_case_insensitivity() {
249 let (msg, _) = format_error_with_guidance("DEVICE NOT FOUND");
251 assert_eq!(msg, "Device not found");
252
253 let (msg, _) = format_error_with_guidance("TIMED OUT");
254 assert_eq!(msg, "Connection timed out");
255
256 let (msg, _) = format_error_with_guidance("OUT OF RANGE");
257 assert_eq!(msg, "Device out of range");
258 }
259}