use std::env;
use std::thread::sleep;
use std::time::Duration;
use zwo_mount_control::{
HorizontalPosition, MockMount, Mount, SerialMount, SiteLocation, SlewRate,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
println!("ZWO Mount Control - Basic Example");
println!("==================================\n");
let args: Vec<String> = env::args().collect();
let specified_port = args.get(1).cloned();
let mut mount: Box<dyn Mount> = match try_connect_real_mount(specified_port) {
Some(m) => {
println!("Connected to real mount!\n");
m
}
None => {
println!("No real mount found, using mock mount for demonstration.\n");
let mut mock = MockMount::with_position(0.0, 45.0);
mock.connect()?;
Box::new(mock)
}
};
let model = mount.get_model().unwrap_or_else(|_| "Unknown".to_string());
let firmware = mount
.get_firmware_version()
.unwrap_or_else(|_| "Unknown".to_string());
println!("Mount Model: {}", model);
println!("Firmware: {}\n", firmware);
println!("Setting observer location...");
match mount.set_site_location(SiteLocation::new(34.0522, -118.2437, 71.0)) {
Ok(_) => println!(" Location: 34.0522°N, 118.2437°W, 71m\n"),
Err(e) => println!(" Warning: Could not set location ({}), continuing...\n", e),
}
if mount.is_parked()? {
println!("Unparking mount...");
mount.unpark()?;
}
println!("Setting Alt-Az mode...");
match mount.set_altaz_mode() {
Ok(_) => println!(
" Mode: {:?}\n",
mount
.get_mount_mode()
.unwrap_or(zwo_mount_control::MountMode::AltAz)
),
Err(e) => println!(
" Warning: Could not set Alt-Az mode ({}), continuing...\n",
e
),
}
println!("Setting maximum slew rate...");
match mount.set_slew_rate(SlewRate::MAX) {
Ok(_) => println!(" Slew rate set to maximum (9)\n"),
Err(e) => println!(" Warning: Could not set slew rate ({})\n", e),
}
println!("Going to home position...");
match mount.go_home() {
Ok(_) => {
while mount.is_slewing().unwrap_or(false) {
sleep(Duration::from_millis(100));
}
println!(" Home position reached\n");
}
Err(e) => println!(" Warning: Could not go home ({}), continuing...\n", e),
}
match mount.get_altaz() {
Ok(pos) => println!("Current position: {}\n", pos),
Err(e) => println!("Could not get position: {}\n", e),
}
let target = HorizontalPosition::new(180.0, 45.0); println!("Slewing to Az=180°, Alt=45°...");
println!(" (Using proportional control loop - this may take a moment)");
match mount.goto_altaz(target) {
Ok(_) => {
println!(" Slew complete!");
match mount.get_altaz() {
Ok(final_pos) => println!(" Final position: {}\n", final_pos),
Err(e) => println!(" Could not get final position: {}\n", e),
}
}
Err(e) => println!(" Could not slew: {}\n", e),
}
println!("Parking mount...");
if let Err(e) = mount.park() {
println!(" Warning: Could not park ({})", e);
}
println!("Disconnecting...");
if let Err(e) = mount.disconnect() {
println!(" Warning: Could not disconnect ({})", e);
}
println!("\nDone!");
Ok(())
}
fn try_connect_real_mount(specified_port: Option<String>) -> Option<Box<dyn Mount>> {
use zwo_mount_control::serial_mount::SerialConfig;
if let Some(port) = specified_port {
println!("Trying specified port: {}", port);
let mut mount = SerialMount::new(&port);
if mount.connect().is_ok() {
return Some(Box::new(mount));
} else {
println!(" Failed to connect to {}", port);
return None;
}
}
println!("Searching for ZWO mount...");
let ports = SerialMount::list_ports();
if ports.is_empty() {
println!(" No serial ports found.");
return None;
}
let likely_ports: Vec<_> = ports
.into_iter()
.filter(|p| {
let p_lower = p.to_lowercase();
(p_lower.contains("usb") || p_lower.contains("acm") || p_lower.contains("serial"))
&& !p_lower.contains("debug")
&& !p_lower.contains("bluetooth")
})
.collect();
if likely_ports.is_empty() {
println!(" No likely mount ports found.");
return None;
}
println!(
" Checking {} port(s): {:?}",
likely_ports.len(),
likely_ports
);
for port in &likely_ports {
println!(" Trying {}...", port);
let config = SerialConfig::new(port)
.with_timeout(1000) .with_retry_count(1); let mut mount = SerialMount::with_config(config);
match mount.connect() {
Ok(_) => {
if let Ok(model) = mount.get_model() {
let model_upper = model.to_uppercase();
if model_upper.contains("ZWO")
|| model_upper.contains("AM5")
|| model_upper.contains("AM3")
|| model_upper.contains("AM")
{
println!(" Found ZWO mount: {} on {}", model, port);
let _ = mount.disconnect();
let mut real_mount = SerialMount::new(port);
if real_mount.connect().is_ok() {
return Some(Box::new(real_mount));
}
}
}
let _ = mount.disconnect();
}
Err(_) => continue,
}
}
println!(" No ZWO mount found on any port.");
None
}