#![cfg(all(feature = "c-client", feature = "network-tcp"))]
use mbus_client::services::ClientServices;
use super::app::CApp;
use super::callbacks::MbusCallbacks;
use super::config::{MbusTcpConfig, tcp_config_from_c};
use super::pool::{
MBUS_INVALID_CLIENT_ID, MbusClientId, pool_allocate_tcp, pool_free, with_tcp_client,
};
use crate::c::error::MbusStatusCode;
use crate::c::transport::{CTcpTransport, MbusTransportCallbacks, validate_transport_callbacks};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn mbus_tcp_client_new(
config: *const MbusTcpConfig,
transport_callbacks: *const MbusTransportCallbacks,
callbacks: *const MbusCallbacks,
) -> MbusClientId {
if callbacks.is_null() || transport_callbacks.is_null() {
return MBUS_INVALID_CLIENT_ID;
}
let modbus_config = match unsafe { tcp_config_from_c(config) } {
Ok(c) => c,
Err(_) => return MBUS_INVALID_CLIENT_ID,
};
let cb = unsafe { callbacks.read() };
if cb.on_current_millis.is_none() {
return MBUS_INVALID_CLIENT_ID;
}
let transport_cb = unsafe { transport_callbacks.read() };
if !validate_transport_callbacks(&transport_cb) {
return MBUS_INVALID_CLIENT_ID;
}
let app = CApp::new(cb);
let transport = CTcpTransport::new(transport_cb);
let inner = match ClientServices::new(transport, app, modbus_config) {
Ok(i) => i,
Err(_) => return MBUS_INVALID_CLIENT_ID,
};
match pool_allocate_tcp(inner) {
Ok(id) => id,
Err(_) => MBUS_INVALID_CLIENT_ID,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn mbus_tcp_client_free(id: MbusClientId) {
if id != MBUS_INVALID_CLIENT_ID {
pool_free(id);
}
}
#[unsafe(no_mangle)]
pub extern "C" fn mbus_tcp_connect(id: MbusClientId) -> MbusStatusCode {
with_tcp_client(id, |inner| match inner.reconnect() {
Ok(()) => MbusStatusCode::MbusOk,
Err(e) => MbusStatusCode::from(e),
})
.unwrap_or_else(|e| e)
}
#[unsafe(no_mangle)]
pub extern "C" fn mbus_tcp_disconnect(id: MbusClientId) -> MbusStatusCode {
with_tcp_client(id, |inner| {
inner.disconnect();
MbusStatusCode::MbusOk
})
.unwrap_or_else(|e| e)
}
#[unsafe(no_mangle)]
pub extern "C" fn mbus_tcp_is_connected(id: MbusClientId) -> u8 {
with_tcp_client(id, |inner| if inner.is_connected() { 1 } else { 0 }).unwrap_or(0)
}
#[unsafe(no_mangle)]
pub extern "C" fn mbus_tcp_poll(id: MbusClientId) {
let _ = with_tcp_client(id, |inner| inner.poll());
}
#[unsafe(no_mangle)]
pub extern "C" fn mbus_tcp_has_pending_requests(id: MbusClientId) -> u8 {
with_tcp_client(id, |inner| if inner.has_pending_requests() { 1 } else { 0 }).unwrap_or(0)
}
#[unsafe(no_mangle)]
pub extern "C" fn mbus_tcp_reconnect(id: MbusClientId) -> MbusStatusCode {
with_tcp_client(id, |inner| match inner.reconnect() {
Ok(()) => MbusStatusCode::MbusOk,
Err(e) => MbusStatusCode::from(e),
})
.unwrap_or_else(|e| e)
}