use std::ptr::{self, NonNull};
use open62541_sys::{
UA_Client, UA_Client_delete, UA_Client_disconnect, UA_Client_getState, UA_Client_new,
UA_Client_newWithConfig,
};
use crate::{ua, DataType as _, Error};
#[derive(Debug)]
pub struct ClientState {
pub channel_state: ua::SecureChannelState,
pub session_state: ua::SessionState,
pub connect_status: ua::StatusCode,
}
#[derive(Debug)]
pub struct Client(NonNull<UA_Client>);
unsafe impl Send for Client {}
unsafe impl Sync for Client {}
impl Client {
pub(crate) fn new_with_config(config: ua::ClientConfig) -> Self {
let config = config.into_raw();
let inner = unsafe { UA_Client_newWithConfig(ptr::addr_of!(config)) };
let inner = NonNull::new(inner).expect("create UA_Client");
Self(inner)
}
#[must_use]
pub(crate) const unsafe fn as_ptr(&self) -> *const UA_Client {
self.0.as_ptr()
}
#[must_use]
pub(crate) unsafe fn as_mut_ptr(&mut self) -> *mut UA_Client {
self.0.as_ptr()
}
#[allow(dead_code)] pub(crate) fn state(&self) -> ClientState {
log::debug!("Getting state");
let mut channel_state = ua::SecureChannelState::init();
let mut session_state = ua::SessionState::init();
let mut connect_status = ua::StatusCode::init();
unsafe {
UA_Client_getState(
self.as_ptr().cast_mut(),
channel_state.as_mut_ptr(),
session_state.as_mut_ptr(),
connect_status.as_mut_ptr(),
);
}
ClientState {
channel_state,
session_state,
connect_status,
}
}
pub(crate) fn disconnect(mut self) {
log::info!("Disconnecting from endpoint");
let status_code = ua::StatusCode::new(unsafe {
UA_Client_disconnect(self.as_mut_ptr())
});
if let Err(error) = Error::verify_good(&status_code) {
log::warn!("Error while disconnecting client: {error}");
}
}
}
impl Drop for Client {
fn drop(&mut self) {
log::debug!("Deleting client");
unsafe { UA_Client_delete(self.as_mut_ptr()) }
}
}
impl Default for Client {
fn default() -> Self {
let inner = NonNull::new(unsafe { UA_Client_new() }).expect("create UA_Client");
Self(inner)
}
}