From e93e10d14d972300a776a67197665929f5497f61 Mon Sep 17 00:00:00 2001 From: kraemr <93094049+kraemr@users.noreply.github.com> Date: Thu, 23 Oct 2025 20:09:09 +0200 Subject: [PATCH] fixed all warnings and restored original ethercat discovery behaviour --- .../src/ethercat/ethercat_discovery_info.rs | 38 +++++ server/src/ethercat/mod.rs | 1 + server/src/ethercat/setup.rs | 7 +- server/src/loop.rs | 17 +- server/src/main.rs | 150 +++--------------- server/src/serial/init.rs | 125 ++++++++++++++- 6 files changed, 200 insertions(+), 138 deletions(-) create mode 100644 server/src/ethercat/ethercat_discovery_info.rs diff --git a/server/src/ethercat/ethercat_discovery_info.rs b/server/src/ethercat/ethercat_discovery_info.rs new file mode 100644 index 00000000..73e0a915 --- /dev/null +++ b/server/src/ethercat/ethercat_discovery_info.rs @@ -0,0 +1,38 @@ +use std::sync::Arc; + +use control_core::socketio::namespace::NamespaceCacheingLogic; + +use crate::{ + app_state::AppState, + socketio::main_namespace::{ + MainNamespaceEvents, ethercat_interface_discovery_event::EthercatInterfaceDiscoveryEvent, + }, +}; + +pub async fn send_ethercat_discovering(app_state: Arc) { + { + let main_namespace = &mut app_state + .socketio_setup + .namespaces + .write() + .await + .main_namespace; + let event = EthercatInterfaceDiscoveryEvent::Discovering(true).build(); + main_namespace.emit(MainNamespaceEvents::EthercatInterfaceDiscoveryEvent(event)); + } +} +pub async fn send_ethercat_found(app_state: Arc, interface: &str) { + // Notify client via socketio + let interface = interface.to_string(); + let app_state_socketio = app_state.clone(); + smol::block_on(async move { + let main_namespace = &mut app_state_socketio + .socketio_setup + .namespaces + .write() + .await + .main_namespace; + let event = EthercatInterfaceDiscoveryEvent::Done(interface).build(); + main_namespace.emit(MainNamespaceEvents::EthercatInterfaceDiscoveryEvent(event)); + }); +} diff --git a/server/src/ethercat/mod.rs b/server/src/ethercat/mod.rs index 58ebf3a6..50ea7002 100644 --- a/server/src/ethercat/mod.rs +++ b/server/src/ethercat/mod.rs @@ -1,3 +1,4 @@ pub mod config; +pub mod ethercat_discovery_info; pub mod init; pub mod setup; diff --git a/server/src/ethercat/setup.rs b/server/src/ethercat/setup.rs index 67c7c987..8fbca10b 100644 --- a/server/src/ethercat/setup.rs +++ b/server/src/ethercat/setup.rs @@ -52,6 +52,7 @@ pub async fn setup_loop(interface: &str, app_state: Arc) -> Result<(), let _ = set_core_affinity(3); // Set the thread to real-time priority + #[cfg(not(feature = "development-build"))] let _ = set_realtime_priority(); #[cfg(not(all(target_os = "linux", feature = "io-uring")))] @@ -85,13 +86,13 @@ pub async fn setup_loop(interface: &str, app_state: Arc) -> Result<(), // Default 30_000us pdu: Duration::from_micros(30_000), // Default 10ms - eeprom: Duration::from_millis(100), + eeprom: Duration::from_millis(10), // Default 0ms wait_loop_delay: Duration::from_millis(0), // Default 100ms - mailbox_echo: Duration::from_millis(1000), + mailbox_echo: Duration::from_millis(100), // Default 1000ms - mailbox_response: Duration::from_millis(10000), + mailbox_response: Duration::from_millis(1000), }, MainDeviceConfig { // Default RetryBehaviour::None diff --git a/server/src/loop.rs b/server/src/loop.rs index 26c22bf5..09d70a93 100644 --- a/server/src/loop.rs +++ b/server/src/loop.rs @@ -1,4 +1,4 @@ -use crate::app_state::AppState; +use crate::{app_state::AppState, ethercat::setup::setup_loop}; use bitvec::prelude::*; use control_core::machines::connection::MachineConnection; use control_core::realtime::set_core_affinity; @@ -9,8 +9,20 @@ use std::time::Instant; use tracing::{instrument, trace_span}; pub fn start_loop_thread( + interface: &str, app_state: Arc, ) -> Result, std::io::Error> { + let res = smol::block_on(async { setup_loop(interface, app_state.clone()).await }); + match res { + Ok(_) => tracing::info!("Successfully initialized EtherCAT network"), + Err(e) => { + tracing::error!( + "[{}::init_loop] Failed to initialize EtherCAT network \n{:?}", + module_path!(), + e + ); + } + } // Start control loop let res = std::thread::Builder::new() .name("loop".to_owned()) @@ -43,7 +55,8 @@ pub fn start_loop_thread( #[cfg(feature = "development-build")] std::thread::park_timeout(std::time::Duration::from_millis(600)); } - // Exit the entire program if the Loop fails (gets restarted by systemd if running on NixOS) + // Exit the entire program if the Loop fails + // gets restarted by systemd if running on NixOS, or different distro wtih the same sysd service std::process::exit(1); }); return res; diff --git a/server/src/main.rs b/server/src/main.rs index bd8fbf10..3ca971dc 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,34 +1,21 @@ -use anyhow::Result; -use control_core::{ - machines::identification::MachineIdentificationUnique, - serial::{ - SerialDeviceIdentification, SerialDeviceNew, SerialDeviceNewParams, - serial_detection::SerialDetection, - }, - socketio::namespace::NamespaceCacheingLogic, -}; use futures::{FutureExt, select}; -use machines::{laser::LaserMachine, registry::MACHINE_REGISTRY}; #[cfg(feature = "mock-machine")] use mock::init::init_mock; -use serialport::UsbPortInfo; #[cfg(feature = "mock-machine")] pub mod mock; use crate::panic::init_panic_handling; use app_state::AppState; -use ethercat::init::start_interface_discovery; +use ethercat::{ + ethercat_discovery_info::{send_ethercat_discovering, send_ethercat_found}, + init::start_interface_discovery, +}; use r#loop::start_loop_thread; use rest::init::start_api_thread; -use serial::{ - devices::laser::Laser, init::start_serial_discovery, registry::SERIAL_DEVICE_REGISTRY, -}; -use socketio::{ - main_namespace::{MainNamespaceEvents, machines_event::MachinesEventBuilder}, - queue::start_socketio_queue, -}; -use std::{collections::HashMap, sync::Arc}; +use serial::init::{handle_serial_device_hotplug, start_serial_discovery}; +use socketio::queue::start_socketio_queue; +use std::sync::Arc; pub mod app_state; pub mod ethercat; pub mod logging; @@ -40,112 +27,6 @@ pub mod rest; pub mod serial; pub mod socketio; -// This function handles a disconnection and or reconnection of Laser -// You can easily rewrite it when we have more serialdevices -// TODO: Add A static list of known SeriadeviceIdents -async fn handle_serial_device_hotplug( - app_state: Arc, - map: Option>, -) { - let laser_ident = SerialDeviceIdentification { - vendor_id: 0x0403, - product_id: 0x6001, - }; - - let laser = match map { - Some(map) => SerialDetection::get_path_by_id(laser_ident, map), - None => None, - }; - - let mut unique_ident: Option = None; - - { - let machines = app_state.machines.read_arc_blocking(); - for (id, _) in machines.iter() { - if id.machine_identification == LaserMachine::MACHINE_IDENTIFICATION { - unique_ident = Some(id.clone()); - break; - } - } - } - - // Machine isnt connected, so add it back - if laser.is_some() && unique_ident.is_none() { - let serial_params = SerialDeviceNewParams { - path: laser.unwrap(), - }; - let _ = match Laser::new_serial(&serial_params) { - Ok((device_identification, serial_device)) => { - { - let mut machines = app_state.machines.write().await; - machines.add_serial_device( - &device_identification, - serial_device, - &MACHINE_REGISTRY, - app_state.socketio_setup.socket_queue_tx.clone(), - Arc::downgrade(&app_state.machines), - ); - } - - let app_state_event = app_state.clone(); - let main_namespace = &mut app_state_event - .socketio_setup - .namespaces - .write() - .await - .main_namespace; - let event = MachinesEventBuilder().build(app_state_event.clone()); - main_namespace.emit(MainNamespaceEvents::MachinesEvent(event)); - } - _ => (), - }; - } else if laser.is_none() && unique_ident.is_some() { - tracing::info!("hello non existing laser"); - let serial_params = SerialDeviceNewParams { - path: "".to_string(), - }; - - let _ = match Laser::new_serial(&serial_params) { - Ok((device_identification, _)) => { - app_state - .machines - .write() - .await - .remove_serial_device(&device_identification); - drop(app_state.machines.clone()); - - app_state - .machines - .write_arc() - .await - .serial_machines - .remove(&unique_ident.clone().unwrap()); - - app_state - .machines - .write_arc() - .await - .ethercat_machines - .remove(&unique_ident.clone().unwrap()); - - drop(app_state.machines.clone()); - - let main_namespace = &mut app_state - .socketio_setup - .namespaces - .write() - .await - .main_namespace; - - tracing::info!("{:?}", app_state.machines); - let event = MachinesEventBuilder().build(app_state.clone()); - main_namespace.emit(MainNamespaceEvents::MachinesEvent(event)); - } - _ => (), - }; - } -} - fn main() { logging::init_tracing(); tracing::info!("Tracing initialized successfully"); @@ -154,28 +35,35 @@ fn main() { let app_state = Arc::new(AppState::new()); let _ = start_api_thread(app_state.clone()); - let _ = start_loop_thread(app_state.clone()); - let mut socketio_fut = start_socketio_queue(app_state.clone()).fuse(); let mut ethercat_fut = start_interface_discovery().fuse(); let mut serial_fut = start_serial_discovery().fuse(); + smol::block_on(async { send_ethercat_discovering(app_state.clone()).await }); + smol::block_on(async { loop { // lets the async runtime decide which future to run next select! { res = ethercat_fut => { - // Should only complete once tracing::info!("EtherCAT task finished: {:?}", res); + match res { + Ok(interface) => + { + send_ethercat_found(app_state.clone(), &interface).await; + let _ = start_loop_thread(&interface, app_state.clone()); + }, + Err(_) => (), + }; + }, res = serial_fut => { - // tracing::info!("Serial discovery finished: {:?}", res); let _ = handle_serial_device_hotplug(app_state.clone(),res).await; serial_fut = start_serial_discovery().fuse(); }, res = socketio_fut => { // In theory it should never finish - tracing::info!("SocketIO task finished: {:?}", res); + tracing::warn!("SocketIO task finished: {:?}", res); }, _ = smol::Timer::after(std::time::Duration::from_millis(250)).fuse() => {} // Nothing to do just sleep } diff --git a/server/src/serial/init.rs b/server/src/serial/init.rs index c2319948..a0d6220b 100644 --- a/server/src/serial/init.rs +++ b/server/src/serial/init.rs @@ -1,7 +1,22 @@ -use control_core::serial::serial_detection::SerialDetection; +use control_core::{ + machines::identification::MachineIdentificationUnique, + serial::{ + SerialDeviceIdentification, SerialDeviceNew, SerialDeviceNewParams, + serial_detection::SerialDetection, + }, + socketio::namespace::NamespaceCacheingLogic, +}; use serialport::UsbPortInfo; use smol::Task; -use std::{collections::HashMap, time::Duration}; +use std::{collections::HashMap, sync::Arc, time::Duration}; + +use crate::{ + app_state::AppState, + machines::{laser::LaserMachine, registry::MACHINE_REGISTRY}, + socketio::main_namespace::{MainNamespaceEvents, machines_event::MachinesEventBuilder}, +}; + +use super::devices::laser::Laser; // Async function that runs until at least one serial device is found. pub async fn find_serial() -> Option> { @@ -18,3 +33,109 @@ pub async fn find_serial() -> Option> { pub fn start_serial_discovery() -> Task>> { smol::spawn(find_serial()) } + +// This function handles a disconnection and or reconnection of Laser +// You can easily rewrite it when we have more serialdevices +// TODO: Add A static list of known SeriadeviceIdents +pub async fn handle_serial_device_hotplug( + app_state: Arc, + map: Option>, +) { + let laser_ident = SerialDeviceIdentification { + vendor_id: 0x0403, + product_id: 0x6001, + }; + + let laser = match map { + Some(map) => SerialDetection::get_path_by_id(laser_ident, map), + None => None, + }; + + let mut unique_ident: Option = None; + + { + let machines = app_state.machines.read_arc_blocking(); + for (id, _) in machines.iter() { + if id.machine_identification == LaserMachine::MACHINE_IDENTIFICATION { + unique_ident = Some(id.clone()); + break; + } + } + } + + // Machine isnt connected, so add it back + if laser.is_some() && unique_ident.is_none() { + let serial_params = SerialDeviceNewParams { + path: laser.unwrap(), + }; + let _ = match Laser::new_serial(&serial_params) { + Ok((device_identification, serial_device)) => { + { + let mut machines = app_state.machines.write().await; + machines.add_serial_device( + &device_identification, + serial_device, + &MACHINE_REGISTRY, + app_state.socketio_setup.socket_queue_tx.clone(), + Arc::downgrade(&app_state.machines), + ); + } + + let app_state_event = app_state.clone(); + let main_namespace = &mut app_state_event + .socketio_setup + .namespaces + .write() + .await + .main_namespace; + let event = MachinesEventBuilder().build(app_state_event.clone()); + main_namespace.emit(MainNamespaceEvents::MachinesEvent(event)); + } + _ => (), + }; + } else if laser.is_none() && unique_ident.is_some() { + tracing::info!("hello non existing laser"); + let serial_params = SerialDeviceNewParams { + path: "".to_string(), + }; + + let _ = match Laser::new_serial(&serial_params) { + Ok((device_identification, _)) => { + app_state + .machines + .write() + .await + .remove_serial_device(&device_identification); + drop(app_state.machines.clone()); + + app_state + .machines + .write_arc() + .await + .serial_machines + .remove(&unique_ident.clone().unwrap()); + + app_state + .machines + .write_arc() + .await + .ethercat_machines + .remove(&unique_ident.clone().unwrap()); + + drop(app_state.machines.clone()); + + let main_namespace = &mut app_state + .socketio_setup + .namespaces + .write() + .await + .main_namespace; + + tracing::info!("{:?}", app_state.machines); + let event = MachinesEventBuilder().build(app_state.clone()); + main_namespace.emit(MainNamespaceEvents::MachinesEvent(event)); + } + _ => (), + }; + } +}