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 }
118
119 window_manager.process_event(event);
121 }
122 Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
123 window_manager.check_window_expiry();
125 }
126 Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
127 break;
128 }
129 }
130
131 for window in window_manager.take_completed_windows() {
133 transparency_log.record_window_completed();
134
135 let features = compute_features(&window);
136 let snapshot = hsi_builder.build(&window, &features);
137
138 println!();
139 println!("=== Window Completed ===");
140 println!(" Duration: {:.1}s", window.duration_secs());
141 println!(" Keyboard events: {}", window.keyboard_events.len());
142 println!(" Mouse events: {}", window.mouse_events.len());
143 println!();
144 println!(" Keyboard Features:");
145 println!(
146 " Typing rate: {:.2} keys/sec",
147 features.keyboard.typing_rate
148 );
149 println!(" Pause count: {}", features.keyboard.pause_count);
150 println!(" Burst index: {:.3}", features.keyboard.burst_index);
151 println!();
152 println!(" Mouse Features:");
153 println!(
154 " Activity rate: {:.2} moves/sec",
155 features.mouse.mouse_activity_rate
156 );
157 println!(" Mean velocity: {:.2}", features.mouse.mean_velocity);
158 println!(
159 " Click rate: {:.2} clicks/sec",
160 features.mouse.click_rate
161 );
162 println!();
163 println!(" Behavioral Signals:");
164 println!(
165 " Interaction rhythm: {:.3}",
166 features.behavioral.interaction_rhythm
167 );
168 println!(" Friction: {:.3}", features.behavioral.friction);
169 println!(
170 " Motor stability: {:.3}",
171 features.behavioral.motor_stability
172 );
173 println!(
174 " Focus continuity: {:.3}",
175 features.behavioral.focus_continuity_proxy
176 );
177 println!();
178
179 let json = serde_json::to_string_pretty(&snapshot).unwrap();
181 println!(" HSI Snapshot (truncated):");
182 for line in json.lines().take(20) {
183 println!(" {line}");
184 }
185 println!(" ...");
186 println!();
187 }
188
189 if event_count > 0 && event_count % 200 == 0 {
191 let elapsed = start.elapsed().as_secs();
192 println!(" [{elapsed}/30s] Processed {event_count} events...");
193 }
194 }
195
196 println!();
198 println!("Stopping capture...");
199 collector.stop();
200
201 window_manager.flush();
203 for window in window_manager.take_completed_windows() {
204 println!("Final window: {} events", window.event_count());
205 transparency_log.record_window_completed();
206 }
207
208 println!();
210 println!("{}", transparency_log.summary());
211 println!();
212 println!("Demo complete!");
213}