Skip to content

Support for implementing a separate connect method #37

@EFeru

Description

@EFeru

Dear @birkenfeld,

I am implementing a separate method to connect to a PLC via ADS and then read values in another method. I use Tauri shared state to do this. The connect method looks like this:

use tauri::Manager;
use tauri::State;
use std::sync::Mutex;


#[derive(Default)]
pub struct AppState {
    device: Option<ads::Device>,
    is_connected_ads: bool,
}

#[tauri::command]
pub async fn connect(app_state: State<'_, Mutex<AppState>>, ip: String, port: String)   {
    // Reset connected
    let mut app_state = app_state.lock().unwrap();
    app_state.is_connected_ads = false;

    // Parse IP and port
    let ip_array: Vec<u8> = ip
        .split('.')
        .map(|s| s.parse().map_err(|_| "Invalid IP format".to_string()))
        .collect::<Result<_, _>>()?;
    if ip_array.len() != 6 {
        return Err("IP address must have 6 segments".to_string());
    }
    let ip_array: [u8; 6] = ip_array.try_into().map_err(|_| "Invalid IP array conversion".to_string())?;
    let port: u16 = port.parse().map_err(|_| "Invalid port format".to_string())?;

    // Create an ADS client
    let client = ads::Client::new(("127.0.0.1", ads::PORT), ads::Timeouts::none(), ads::Source::Request).map_err(|e| format!("Failed to create ADS client: {:?}", e))?;

    // Create a device
    let ams_addr = ads::AmsAddr::new(ip_array.into(), port);
    let device = client.device(ams_addr);

    // Check device state
    let (ads_state, _) = device.get_state().map_err(|e| format!("Failed to get device state: {:?}", e))?;
    if ads_state != ads::AdsState::Run {
        return Err("Device is not in RUN state".to_string());
    }

    // Store the device in shared state
    app_state.device = Some(device).into();

    // Mark is connected
    app_state.is_connected_ads = true;
}

However, the issue is that Device has a life parameter, which apparently is not supported by Tauri state structure AppState.

error[E0106]: missing lifetime specifier
 --> src\commands.rs:9:25
  |
9 |     device: Option<ads::Device>,
  |                         ^^^^^^ expected named lifetime parameter
  |
help: consider introducing a named lifetime parameter
  |
7 ~ pub struct AppState<'a> {
9 ~     device: Option<ads::Device<'a>>,
  |

If I implement the suggestion, then I get:

 | #[tauri::command]
    | ^^^^^^^^^^^^^^^^^ the trait `CommandArg<'_, tauri_runtime_wry::Wry<EventLoopMessage>>` is not implemented for `tauri::State<'_, std::sync::Mutex<AppState<'_>>>`

I don't know any work arround, so I was wondering how necessary is life parameter in the Device and could we switch it to simple type similar to the Client struct?

ads-rs/src/symbol.rs

Lines 17 to 28 in e0d3bf9

pub struct Handle<'c> {
device: Device<'c>,
handle: u32,
}
impl<'c> Handle<'c> {
/// Create a new handle to a single symbol.
pub fn new(device: Device<'c>, symbol: &str) -> Result<Self> {
let mut handle_bytes = [0; 4];
device.write_read_exact(index::GET_SYMHANDLE_BYNAME, 0, symbol.as_bytes(), &mut handle_bytes)?;
Ok(Self { device, handle: u32::from_le_bytes(handle_bytes) })
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions