use profirust::dp; use profirust::fdl; use profirust::phy; mod tester_io; mod valve_terminal; // Bus Parameters const MASTER_ADDRESS: u8 = 1; const BUS_DEVICE: &'static str = "/dev/ttyUSB0"; const BAUDRATE: profirust::Baudrate = profirust::Baudrate::B500000; fn main() -> ! { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")) .format_timestamp_micros() .init(); log::info!("Ventilinsel Teststation"); let mut dp_scanner = dp::scan::DpScanner::new(); let mut dp_master = dp::DpMaster::new(vec![]); let mut tester_io = tester_io::TesterIo::new(&mut dp_master, BAUDRATE); let mut valve_terminal = valve_terminal::ValveTerminal::new(&mut dp_master, BAUDRATE); let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(MASTER_ADDRESS, BAUDRATE) // We use a rather large T_slot time because USB-RS485 converters // can induce large delays at times. .slot_bits(2500) // 2 Sekunden Watchdog Timeout .watchdog_timeout(profirust::time::Duration::from_secs(2)) .build_verified(&dp_master), ); // We must not poll() too often or to little. T_slot / 2 seems to be a good compromise. let sleep_time: std::time::Duration = (fdl.parameters().slot_time() / 2).into(); log::info!("Verbindung mit dem Bus wird aufgebaut..."); let mut phy = phy::LinuxRs485Phy::new(BUS_DEVICE, fdl.parameters().baudrate); fdl.set_online(); dp_master.enter_operate(); loop { fdl.poll_multi( profirust::time::Instant::now(), &mut phy, &mut [&mut dp_master, &mut dp_scanner], ); let dp_events = dp_master.take_last_events(); tester_io.update(&mut dp_master, &dp_events); valve_terminal.update(&mut dp_master, &dp_events); // Ventil Zustände von den Eingängen auf die Ventilausgänge übertragen. valve_terminal.update_valve_states(tester_io.valve_states()); if valve_terminal.is_running(&mut dp_master) { tester_io.set_state(tester_io::TesterStatus::ValveTerminalConnected); } else if valve_terminal.error() { tester_io.set_state(tester_io::TesterStatus::Error); } else { tester_io.set_state(tester_io::TesterStatus::Ready); } let scanner_event = dp_scanner.take_last_event(); match scanner_event { Some(dp::scan::DpScanEvent::PeripheralFound(desc)) => { if valve_terminal.check_ident(desc.ident) { // Wenn die Ventilinsel nicht erreichbar ist, wird eine neue Adresse vom "DP Scanner" // übernommen. if !valve_terminal.is_running(&mut dp_master) { log::info!( "Ventilinsel an Adresse #{} gefunden. Parametrieren...", desc.address ); valve_terminal.init_at_address(desc.address, &mut dp_master); } else { // Alte Ventilinsel ist noch aktiv?? log::warn!( "Neue Ventilinsel an Adresse #{} gefunden, obwohl alte noch aktiv. Wird ignoriert.", desc.address ); } } else { log::info!("Andere Station an Adresse #{} gefunden:", desc.address); log::info!(" - Ident: 0x{:04x}", desc.ident); } } Some(dp::scan::DpScanEvent::PeripheralLost(address)) => { log::info!("Station an Adresse #{} verloren.", address); } _ => (), } std::thread::sleep(sleep_time); } }