pub struct EventWindow {
pub start: DateTime<Utc>,
pub end: DateTime<Utc>,
pub keyboard_events: Vec<KeyboardEvent>,
pub mouse_events: Vec<MouseEvent>,
pub shortcut_events: Vec<ShortcutEvent>,
pub is_session_start: bool,
pub app_id: Option<String>,
}Expand description
A time window containing collected events.
Fields§
§start: DateTime<Utc>Start time of the window
end: DateTime<Utc>End time of the window
keyboard_events: Vec<KeyboardEvent>Keyboard events in this window
mouse_events: Vec<MouseEvent>Mouse events in this window
shortcut_events: Vec<ShortcutEvent>Shortcut events in this window
is_session_start: boolWhether this window marks the start of a new session
app_id: Option<String>Bundle identifier of the frontmost application when this window completed. Only available on macOS. Privacy: no window titles or content captured.
Implementations§
Source§impl EventWindow
impl EventWindow
Sourcepub fn new(start: DateTime<Utc>, duration: Duration) -> Self
pub fn new(start: DateTime<Utc>, duration: Duration) -> Self
Create a new empty window starting at the given time.
Sourcepub fn contains(&self, timestamp: DateTime<Utc>) -> bool
pub fn contains(&self, timestamp: DateTime<Utc>) -> bool
Check if a timestamp falls within this window.
Sourcepub fn add_event(&mut self, event: SensorEvent)
pub fn add_event(&mut self, event: SensorEvent)
Add an event to this window.
Sourcepub fn event_count(&self) -> usize
pub fn event_count(&self) -> usize
Get the total number of events in this window.
Examples found in repository?
examples/capture_demo.rs (line 214)
26fn main() {
27 println!("Synheart Sensor Agent - Capture Demo");
28 println!("=====================================");
29 println!();
30
31 // Display privacy declaration
32 println!("{PRIVACY_DECLARATION}");
33 println!();
34
35 // Check for permission
36 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 // Create components
52 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); // 10s windows, 5min session gap
59 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 // Start collection
69 if let Err(e) = collector.start() {
70 eprintln!("Error starting collector: {e}");
71 return;
72 }
73
74 // Set up stop flag
75 let running = Arc::new(AtomicBool::new(true));
76 let r = running.clone();
77
78 // Set up Ctrl+C handler
79 ctrlc::set_handler(move || {
80 r.store(false, Ordering::SeqCst);
81 })
82 .expect("Error setting Ctrl+C handler");
83
84 // Run for 30 seconds
85 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 // Receive events with timeout
91 match receiver.recv_timeout(Duration::from_millis(100)) {
92 Ok(event) => {
93 event_count += 1;
94
95 // Log event type
96 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 // Process in window manager
130 window_manager.process_event(event);
131 }
132 Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
133 // Check for window expiry
134 window_manager.check_window_expiry();
135 }
136 Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
137 break;
138 }
139 }
140
141 // Process completed windows
142 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 // Show snippet of HSI JSON
190 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 // Show progress
200 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 // Stop collection
207 println!();
208 println!("Stopping capture...");
209 collector.stop();
210
211 // Flush remaining window
212 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 // Final statistics
219 println!();
220 println!("{}", transparency_log.summary());
221 println!();
222 println!("Demo complete!");
223}Sourcepub fn duration_secs(&self) -> f64
pub fn duration_secs(&self) -> f64
Get the duration of this window in seconds.
Examples found in repository?
examples/capture_demo.rs (line 150)
26fn main() {
27 println!("Synheart Sensor Agent - Capture Demo");
28 println!("=====================================");
29 println!();
30
31 // Display privacy declaration
32 println!("{PRIVACY_DECLARATION}");
33 println!();
34
35 // Check for permission
36 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 // Create components
52 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); // 10s windows, 5min session gap
59 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 // Start collection
69 if let Err(e) = collector.start() {
70 eprintln!("Error starting collector: {e}");
71 return;
72 }
73
74 // Set up stop flag
75 let running = Arc::new(AtomicBool::new(true));
76 let r = running.clone();
77
78 // Set up Ctrl+C handler
79 ctrlc::set_handler(move || {
80 r.store(false, Ordering::SeqCst);
81 })
82 .expect("Error setting Ctrl+C handler");
83
84 // Run for 30 seconds
85 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 // Receive events with timeout
91 match receiver.recv_timeout(Duration::from_millis(100)) {
92 Ok(event) => {
93 event_count += 1;
94
95 // Log event type
96 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 // Process in window manager
130 window_manager.process_event(event);
131 }
132 Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
133 // Check for window expiry
134 window_manager.check_window_expiry();
135 }
136 Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
137 break;
138 }
139 }
140
141 // Process completed windows
142 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 // Show snippet of HSI JSON
190 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 // Show progress
200 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 // Stop collection
207 println!();
208 println!("Stopping capture...");
209 collector.stop();
210
211 // Flush remaining window
212 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 // Final statistics
219 println!();
220 println!("{}", transparency_log.summary());
221 println!();
222 println!("Demo complete!");
223}Trait Implementations§
Source§impl Clone for EventWindow
impl Clone for EventWindow
Source§fn clone(&self) -> EventWindow
fn clone(&self) -> EventWindow
Returns a duplicate of the value. Read more
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from
source. Read moreSource§impl Debug for EventWindow
impl Debug for EventWindow
Source§impl<'de> Deserialize<'de> for EventWindow
impl<'de> Deserialize<'de> for EventWindow
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
Auto Trait Implementations§
impl Freeze for EventWindow
impl RefUnwindSafe for EventWindow
impl Send for EventWindow
impl Sync for EventWindow
impl Unpin for EventWindow
impl UnwindSafe for EventWindow
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more