pub struct ActionDriver { /* private fields */ }Expand description
Direct 1:1 translation layer between Actions and NanonisClient calls No safety checks, no validation - maximum performance and flexibility
Implementations§
Source§impl ActionDriver
impl ActionDriver
Sourcepub fn new(addr: &str, port: u16) -> Result<Self, NanonisError>
pub fn new(addr: &str, port: u16) -> Result<Self, NanonisError>
Create a new ActionDriver with the given client
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let mut driver = ActionDriver::new("127.0.0.1", 6501)?;
7
8 for _ in 0..10 {
9 driver.execute_chain(vec![
10 rusty_tip::Action::AutoApproach {
11 wait_until_finished: true,
12 timeout: Duration::from_secs(10),
13 },
14 rusty_tip::Action::PulseRetract {
15 pulse_width: Duration::from_millis(500),
16 pulse_height_v: 5.0,
17 },
18 rusty_tip::Action::Withdraw {
19 wait_until_finished: true,
20 timeout: Duration::from_secs(1),
21 },
22 ])?;
23
24 sleep(Duration::from_secs(1));
25 }
26 Ok(())
27}More examples
4fn main() -> Result<(), Box<dyn Error>> {
5 let mut driver = ActionDriver::new("127.0.0.1", 6501)?;
6
7 let _freq_shift = rusty_tip::SignalIndex(76);
8
9 let z_pos = rusty_tip::SignalIndex(30);
10
11 driver.execute(rusty_tip::Action::Withdraw {
12 wait_until_finished: true,
13 timeout: Duration::from_secs(5),
14 })?;
15
16 driver.execute(rusty_tip::Action::AutoApproach {
17 wait_until_finished: true,
18 timeout: Duration::from_secs(300),
19 })?;
20
21 if let Some(osci_data) = driver.read_oscilloscope_with_stability(
22 z_pos,
23 // Some(TriggerConfig::new(
24 // rusty_tip::types::OsciTriggerMode::Level,
25 // rusty_tip::TriggerSlope::Falling,
26 // 49.0e-12,
27 // 0.0,
28 // )),
29 None,
30 rusty_tip::types::DataToGet::Stable {
31 readings: 1,
32 timeout: Duration::from_secs(2),
33 },
34 stability::trend_analysis_stability,
35 )? {
36 // Use the new plotting function - much cleaner!
37 rusty_tip::plot_values(&osci_data.data, Some("Z-Position Oscilloscope Data"), None, None)?;
38
39 let is_stable = stability::trend_analysis_stability(&osci_data.data);
40 println!("Stability result: {}", is_stable);
41 };
42
43 Ok(())
44}16fn main() -> Result<(), Box<dyn std::error::Error>> {
17 env_logger::init();
18
19 // Create ActionDriver
20 let driver = ActionDriver::new("127.0.0.1", 6501)?;
21
22 // Create controller with custom pulse stepping parameters
23 let mut custom_controller = TipController::new(driver, SignalIndex(76), 2.0, (-2.0, 0.0));
24
25 let file_path = create_log_file_path()?;
26 println!("{file_path:?}");
27
28 // Configure custom pulse stepping parameters with dynamic threshold
29 custom_controller
30 //.set_pulse_stepping(1.5, Box::new(|signal| signal.abs() / 10.0), 4, 8.0)
31 .set_pulse_stepping_fixed(1.5, 2.0, 4, 10.0)
32 .set_stability_threshold(5)
33 .with_logger(Logger::new(file_path, 5));
34
35 // Create atomic flag for graceful shutdown
36 let running = Arc::new(AtomicBool::new(true));
37 let running_clone = Arc::clone(&running);
38
39 // Wrap controller in Arc<Mutex<>> for signal handler
40 let controller = Arc::new(Mutex::new(custom_controller));
41 let controller_clone = Arc::clone(&controller);
42
43 // Set up Ctrl-C handler to flush logger and signal stop
44 ctrlc::set_handler(move || {
45 info!("Received Ctrl-C, signaling stop and flushing logger...");
46 running_clone.store(false, Ordering::SeqCst);
47
48 if let Ok(mut ctrl) = controller_clone.lock() {
49 // Force flush the logger
50 match ctrl.flush_logger() {
51 Ok(()) => info!("Logger flushed successfully on exit"),
52 Err(e) => info!("Failed to flush logger on exit: {}", e),
53 }
54 }
55 })?;
56
57 // Run control loop with periodic checks for the stop signal
58 let result: Result<(), Box<dyn std::error::Error>> = {
59 let mut ctrl = controller.lock().unwrap();
60
61 // Run in shorter intervals so we can check the stop signal
62 let mut total_elapsed = Duration::from_secs(0);
63 let max_duration = Duration::from_secs(1000);
64 let check_interval = Duration::from_secs(5);
65
66 while total_elapsed < max_duration && running.load(Ordering::SeqCst) {
67 let remaining = max_duration - total_elapsed;
68 let run_duration = check_interval.min(remaining);
69
70 match ctrl.run(run_duration) {
71 Ok(final_state) => {
72 info!("Controller finished with state: {:?}", final_state);
73 break;
74 }
75 Err(e) if e.to_string().contains("Loop timeout") => {
76 // Expected timeout, continue if still running
77 total_elapsed += run_duration;
78 if !running.load(Ordering::SeqCst) {
79 info!("Stop signal received, exiting gracefully");
80 break;
81 }
82 }
83 Err(e) => {
84 info!("Controller failed: {}", e);
85 break;
86 }
87 }
88 }
89
90 Ok(())
91 };
92
93 match result {
94 Ok(()) => {
95 info!("Controller loop completed");
96 }
97 Err(e) => {
98 info!("Controller loop failed: {}", e);
99 }
100 }
101
102 Ok(())
103}Sourcepub fn with_nanonis_client(client: NanonisClient) -> Self
pub fn with_nanonis_client(client: NanonisClient) -> Self
Convenience method to create with NanonisClient
Sourcepub fn client(&self) -> &NanonisClient
pub fn client(&self) -> &NanonisClient
Get a reference to the underlying NanonisClient
Sourcepub fn client_mut(&mut self) -> &mut NanonisClient
pub fn client_mut(&mut self) -> &mut NanonisClient
Get a mutable reference to the underlying NanonisClient
Sourcepub fn execute(&mut self, action: Action) -> Result<ActionResult, NanonisError>
pub fn execute(&mut self, action: Action) -> Result<ActionResult, NanonisError>
Execute a single action with direct 1:1 mapping to client methods
Examples found in repository?
4fn main() -> Result<(), Box<dyn Error>> {
5 let mut driver = ActionDriver::new("127.0.0.1", 6501)?;
6
7 let _freq_shift = rusty_tip::SignalIndex(76);
8
9 let z_pos = rusty_tip::SignalIndex(30);
10
11 driver.execute(rusty_tip::Action::Withdraw {
12 wait_until_finished: true,
13 timeout: Duration::from_secs(5),
14 })?;
15
16 driver.execute(rusty_tip::Action::AutoApproach {
17 wait_until_finished: true,
18 timeout: Duration::from_secs(300),
19 })?;
20
21 if let Some(osci_data) = driver.read_oscilloscope_with_stability(
22 z_pos,
23 // Some(TriggerConfig::new(
24 // rusty_tip::types::OsciTriggerMode::Level,
25 // rusty_tip::TriggerSlope::Falling,
26 // 49.0e-12,
27 // 0.0,
28 // )),
29 None,
30 rusty_tip::types::DataToGet::Stable {
31 readings: 1,
32 timeout: Duration::from_secs(2),
33 },
34 stability::trend_analysis_stability,
35 )? {
36 // Use the new plotting function - much cleaner!
37 rusty_tip::plot_values(&osci_data.data, Some("Z-Position Oscilloscope Data"), None, None)?;
38
39 let is_stable = stability::trend_analysis_stability(&osci_data.data);
40 println!("Stability result: {}", is_stable);
41 };
42
43 Ok(())
44}Sourcepub fn execute_expecting<T>(
&mut self,
action: Action,
) -> Result<T, NanonisError>where
ActionResult: ExpectFromAction<T>,
pub fn execute_expecting<T>(
&mut self,
action: Action,
) -> Result<T, NanonisError>where
ActionResult: ExpectFromAction<T>,
Execute action and extract specific type with validation
This is a convenience method that combines execute() with type extraction, providing better ergonomics while preserving type safety.
§Example
use rusty_tip::{ActionDriver, Action, SignalIndex};
use rusty_tip::types::{DataToGet, OsciData};
let mut driver = ActionDriver::new("127.0.0.1", 6501)?;
let osci_data: OsciData = driver.execute_expecting(Action::ReadOsci {
signal: SignalIndex(24),
trigger: None,
data_to_get: DataToGet::Current,
is_stable: None,
})?;Sourcepub fn execute_chain(
&mut self,
chain: impl Into<ActionChain>,
) -> Result<Vec<ActionResult>, NanonisError>
pub fn execute_chain( &mut self, chain: impl Into<ActionChain>, ) -> Result<Vec<ActionResult>, NanonisError>
Execute a chain of actions sequentially
Examples found in repository?
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let mut driver = ActionDriver::new("127.0.0.1", 6501)?;
7
8 for _ in 0..10 {
9 driver.execute_chain(vec![
10 rusty_tip::Action::AutoApproach {
11 wait_until_finished: true,
12 timeout: Duration::from_secs(10),
13 },
14 rusty_tip::Action::PulseRetract {
15 pulse_width: Duration::from_millis(500),
16 pulse_height_v: 5.0,
17 },
18 rusty_tip::Action::Withdraw {
19 wait_until_finished: true,
20 timeout: Duration::from_secs(1),
21 },
22 ])?;
23
24 sleep(Duration::from_secs(1));
25 }
26 Ok(())
27}Sourcepub fn execute_chain_final(
&mut self,
chain: impl Into<ActionChain>,
) -> Result<ActionResult, NanonisError>
pub fn execute_chain_final( &mut self, chain: impl Into<ActionChain>, ) -> Result<ActionResult, NanonisError>
Execute chain and return only the final result
Sourcepub fn execute_chain_partial(
&mut self,
chain: impl Into<ActionChain>,
) -> Result<Vec<ActionResult>, (Vec<ActionResult>, NanonisError)>
pub fn execute_chain_partial( &mut self, chain: impl Into<ActionChain>, ) -> Result<Vec<ActionResult>, (Vec<ActionResult>, NanonisError)>
Execute chain with early termination on error, returning partial results
Sourcepub fn clear_storage(&mut self)
pub fn clear_storage(&mut self)
Clear all stored values
Sourcepub fn stored_keys(&self) -> Vec<&String>
pub fn stored_keys(&self) -> Vec<&String>
Get all stored value keys
Sourcepub fn read_oscilloscope(
&mut self,
signal: SignalIndex,
trigger: Option<TriggerConfig>,
data_to_get: DataToGet,
) -> Result<Option<OsciData>, NanonisError>
pub fn read_oscilloscope( &mut self, signal: SignalIndex, trigger: Option<TriggerConfig>, data_to_get: DataToGet, ) -> Result<Option<OsciData>, NanonisError>
Convenience method to read oscilloscope data directly
Sourcepub fn read_oscilloscope_with_stability(
&mut self,
signal: SignalIndex,
trigger: Option<TriggerConfig>,
data_to_get: DataToGet,
is_stable: fn(&[f64]) -> bool,
) -> Result<Option<OsciData>, NanonisError>
pub fn read_oscilloscope_with_stability( &mut self, signal: SignalIndex, trigger: Option<TriggerConfig>, data_to_get: DataToGet, is_stable: fn(&[f64]) -> bool, ) -> Result<Option<OsciData>, NanonisError>
Convenience method to read oscilloscope data with custom stability function
Examples found in repository?
4fn main() -> Result<(), Box<dyn Error>> {
5 let mut driver = ActionDriver::new("127.0.0.1", 6501)?;
6
7 let _freq_shift = rusty_tip::SignalIndex(76);
8
9 let z_pos = rusty_tip::SignalIndex(30);
10
11 driver.execute(rusty_tip::Action::Withdraw {
12 wait_until_finished: true,
13 timeout: Duration::from_secs(5),
14 })?;
15
16 driver.execute(rusty_tip::Action::AutoApproach {
17 wait_until_finished: true,
18 timeout: Duration::from_secs(300),
19 })?;
20
21 if let Some(osci_data) = driver.read_oscilloscope_with_stability(
22 z_pos,
23 // Some(TriggerConfig::new(
24 // rusty_tip::types::OsciTriggerMode::Level,
25 // rusty_tip::TriggerSlope::Falling,
26 // 49.0e-12,
27 // 0.0,
28 // )),
29 None,
30 rusty_tip::types::DataToGet::Stable {
31 readings: 1,
32 timeout: Duration::from_secs(2),
33 },
34 stability::trend_analysis_stability,
35 )? {
36 // Use the new plotting function - much cleaner!
37 rusty_tip::plot_values(&osci_data.data, Some("Z-Position Oscilloscope Data"), None, None)?;
38
39 let is_stable = stability::trend_analysis_stability(&osci_data.data);
40 println!("Stability result: {}", is_stable);
41 };
42
43 Ok(())
44}Source§impl ActionDriver
Extension for ActionDriver with execution statistics
impl ActionDriver
Extension for ActionDriver with execution statistics
Sourcepub fn execute_chain_with_stats(
&mut self,
chain: impl Into<ActionChain>,
) -> Result<(Vec<ActionResult>, ExecutionStats), NanonisError>
pub fn execute_chain_with_stats( &mut self, chain: impl Into<ActionChain>, ) -> Result<(Vec<ActionResult>, ExecutionStats), NanonisError>
Execute chain with detailed statistics