capture_demo/
capture_demo.rs1use std::sync::atomic::{AtomicBool, Ordering};
16use std::sync::Arc;
17use std::time::Duration;
18
19use synheart_sensor_agent::{
20 collector::{check_permission, Collector, CollectorConfig, SensorEvent},
21 core::{compute_features, HsiBuilder, WindowManager},
22 transparency::TransparencyLog,
23 PRIVACY_DECLARATION,
24};
25
26fn main() {
27 println!("Synheart Sensor Agent - Capture Demo");
28 println!("=====================================");
29 println!();
30
31 println!("{PRIVACY_DECLARATION}");
33 println!();
34
35 print!("Checking Input Monitoring permission... ");
37 if check_permission() {
38 println!("OK ✓");
39 } else {
40 println!("FAILED ✗");
41 println!();
42 println!("Please grant Input Monitoring permission:");
43 println!("1. Open System Preferences");
44 println!("2. Go to Security & Privacy > Privacy > Input Monitoring");
45 println!("3. Add this application");
46 println!("4. Restart this demo");
47 return;
48 }
49 println!();
50
51 let config = CollectorConfig {
53 capture_keyboard: true,
54 capture_mouse: true,
55 };
56
57 let mut collector = Collector::new(config);
58 let mut window_manager = WindowManager::new(10, 300); let hsi_builder = HsiBuilder::new();
60 let transparency_log = TransparencyLog::new();
61
62 println!("Instance ID: {}", hsi_builder.instance_id());
63 println!();
64 println!("Starting capture for 30 seconds...");
65 println!("Try typing and moving your mouse!");
66 println!();
67
68 if let Err(e) = collector.start() {
70 eprintln!("Error starting collector: {e}");
71 return;
72 }
73
74 let running = Arc::new(AtomicBool::new(true));
76 let r = running.clone();
77
78 ctrlc::set_handler(move || {
80 r.store(false, Ordering::SeqCst);
81 })
82 .expect("Error setting Ctrl+C handler");
83
84 let start = std::time::Instant::now();
86 let receiver = collector.receiver().clone();
87 let mut event_count = 0;
88
89 while running.load(Ordering::SeqCst) && start.elapsed() < Duration::from_secs(30) {
90 match receiver.recv_timeout(Duration::from_millis(100)) {
92 Ok(event) => {
93 event_count += 1;
94
95 match &event {
97 SensorEvent::Keyboard(e) => {
98 transparency_log.record_keyboard_event();
99 if event_count <= 10 || event_count % 50 == 0 {
100 println!(
101 " Keyboard event: {} at {}",
102 if e.is_key_down { "down" } else { "up" },
103 e.timestamp.format("%H:%M:%S%.3f")
104 );
105 }
106 }
107 SensorEvent::Mouse(e) => {
108 transparency_log.record_mouse_event();
109 if event_count <= 10 || event_count % 100 == 0 {
110 println!(
111 " Mouse event: {:?} at {}",
112 e.event_type,
113 e.timestamp.format("%H:%M:%S%.3f")
114 );
115 }
116 }
117 SensorEvent::Shortcut(e) => {
118 transparency_log.record_shortcut_event();
119 if event_count <= 10 || event_count % 50 == 0 {
120 println!(
121 " Shortcut event: {:?} at {}",
122 e.shortcut_type,
123 e.timestamp.format("%H:%M:%S%.3f")
124 );
125 }
126 }
127 }
128
129 window_manager.process_event(event);
131 }
132 Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
133 window_manager.check_window_expiry();
135 }
136 Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
137 break;
138 }
139 }
140
141 for window in window_manager.take_completed_windows() {
143 transparency_log.record_window_completed();
144
145 let features = compute_features(&window);
146 let snapshot = hsi_builder.build(&window, &features);
147
148 println!();
149 println!("=== Window Completed ===");
150 println!(" Duration: {:.1}s", window.duration_secs());
151 println!(" Keyboard events: {}", window.keyboard_events.len());
152 println!(" Mouse events: {}", window.mouse_events.len());
153 println!();
154 println!(" Keyboard Features:");
155 println!(
156 " Typing rate: {:.2} keys/sec",
157 features.keyboard.typing_rate
158 );
159 println!(" Pause count: {}", features.keyboard.pause_count);
160 println!(" Burst index: {:.3}", features.keyboard.burst_index);
161 println!();
162 println!(" Mouse Features:");
163 println!(
164 " Activity rate: {:.2} moves/sec",
165 features.mouse.mouse_activity_rate
166 );
167 println!(" Mean velocity: {:.2}", features.mouse.mean_velocity);
168 println!(
169 " Click rate: {:.2} clicks/sec",
170 features.mouse.click_rate
171 );
172 println!();
173 println!(" Behavioral Signals:");
174 println!(
175 " Interaction rhythm: {:.3}",
176 features.behavioral.interaction_rhythm
177 );
178 println!(" Friction: {:.3}", features.behavioral.friction);
179 println!(
180 " Motor stability: {:.3}",
181 features.behavioral.motor_stability
182 );
183 println!(
184 " Focus continuity: {:.3}",
185 features.behavioral.focus_continuity_proxy
186 );
187 println!();
188
189 let json = serde_json::to_string_pretty(&snapshot).unwrap();
191 println!(" HSI Snapshot (truncated):");
192 for line in json.lines().take(20) {
193 println!(" {line}");
194 }
195 println!(" ...");
196 println!();
197 }
198
199 if event_count > 0 && event_count % 200 == 0 {
201 let elapsed = start.elapsed().as_secs();
202 println!(" [{elapsed}/30s] Processed {event_count} events...");
203 }
204 }
205
206 println!();
208 println!("Stopping capture...");
209 collector.stop();
210
211 window_manager.flush();
213 for window in window_manager.take_completed_windows() {
214 println!("Final window: {} events", window.event_count());
215 transparency_log.record_window_completed();
216 }
217
218 println!();
220 println!("{}", transparency_log.summary());
221 println!();
222 println!("Demo complete!");
223}