#include "wrapper.h"
#include <iostream>
namespace pvxs_wrapper {
void MonitorWrapper::start() {
if (monitor_) {
return;
}
if (!monitor_) {
try {
connect_ = context_.connect(pv_name_).exec();
auto sub = context_.monitor(pv_name_).maskConnected(true).maskDisconnected(true).exec();
monitor_ = std::move(sub);
} catch (const std::exception& e) {
throw PvxsError(std::string("Error starting monitor for '") + pv_name_ + "': " + e.what());
}
}
}
void MonitorWrapper::stop() {
if (monitor_) {
monitor_.reset();
}
if (connect_) {
connect_.reset();
}
}
bool MonitorWrapper::is_running() const {
return monitor_ != nullptr;
}
bool MonitorWrapper::has_update() const {
if (!monitor_) {
return false;
}
try {
return monitor_->pop().valid();
} catch (const std::exception&) {
return false;
}
}
std::unique_ptr<ValueWrapper> MonitorWrapper::get_update(double timeout) {
if (!monitor_) {
throw PvxsError("Monitor client error: '" + pv_name_ + "' doesn't have an active monitor");
}
try {
auto result = monitor_->pop();
if (!result.valid()) {
throw PvxsError("No update available for '" + pv_name_ + "'");
}
return std::make_unique<ValueWrapper>(std::move(result));
} catch (const pvxs::client::Connected& e) {
throw MonitorConnected(std::string("Monitor connected: ") + e.what());
} catch (const pvxs::client::Disconnect& e) {
throw MonitorDisconnected(std::string("Monitor disconnected: ") + e.what());
} catch (const pvxs::client::Finished& e) {
throw MonitorFinished(std::string("Monitor finished: ") + e.what());
} catch (const pvxs::client::RemoteError& e) {
throw MonitorRemoteError(std::string("Monitor remote error: ") + e.what());
} catch (const std::exception& e) {
throw MonitorClientError(std::string("Monitor client error: ") + e.what());
}
}
std::unique_ptr<ValueWrapper> MonitorWrapper::try_get_update() {
if (!monitor_) {
throw PvxsError("Monitor client error: '" + pv_name_ + "' doesn't have an active monitor");
}
try {
auto result = monitor_->pop();
if (result.valid()) {
return std::make_unique<ValueWrapper>(std::move(result));
} else {
return nullptr;
}
} catch (const pvxs::client::Connected& e) {
throw MonitorConnected(std::string("Monitor connected: ") + e.what());
} catch (const pvxs::client::Disconnect& e) {
throw MonitorDisconnected(std::string("Monitor disconnected: ") + e.what());
} catch (const pvxs::client::Finished& e) {
throw MonitorFinished(std::string("Monitor finished: ") + e.what());
} catch (const pvxs::client::RemoteError& e) {
throw MonitorRemoteError(std::string("Monitor remote error: ") + e.what());
} catch (const std::exception& e) {
throw MonitorClientError(std::string("Monitor client error: ") + e.what());
}
}
std::unique_ptr<ValueWrapper> MonitorWrapper::pop() {
if (!monitor_) {
throw PvxsError("Monitor client error: '" + pv_name_ + "' doesn't have an active monitor");
}
try {
auto result = monitor_->pop();
if (result.valid()) {
return std::make_unique<ValueWrapper>(std::move(result));
} else {
return nullptr; }
} catch (const pvxs::client::Connected& e) {
throw MonitorConnected(std::string("Monitor connected: ") + e.what());
} catch (const pvxs::client::Disconnect& e) {
throw MonitorDisconnected(std::string("Monitor disconnected: ") + e.what());
} catch (const pvxs::client::Finished& e) {
throw MonitorFinished(std::string("Monitor finished: ") + e.what());
} catch (const pvxs::client::RemoteError& e) {
throw MonitorRemoteError(std::string("Monitor remote error: ") + e.what());
} catch (const std::exception& e) {
throw MonitorClientError(std::string("Monitor client error: ") + e.what());
}
}
bool MonitorWrapper::is_connected() const {
if (!connect_) {
return false;
}
try {
return connect_->connected();
} catch (const std::exception& e) {
return false;
}
}
std::unique_ptr<MonitorWrapper> context_monitor_create(
ContextWrapper& ctx,
rust::String pv_name) {
return ctx.monitor(std::string(pv_name));
}
void monitor_start(MonitorWrapper& monitor) {
try {
monitor.start();
} catch (const std::exception& e) {
throw PvxsError(std::string("Error starting monitor: ") + e.what());
}
}
void monitor_stop(MonitorWrapper& monitor) {
try {
monitor.stop();
} catch (const std::exception& e) {
throw PvxsError(std::string("Error stopping monitor: ") + e.what());
}
}
bool monitor_is_running(const MonitorWrapper& monitor) {
return monitor.is_running();
}
bool monitor_has_update(const MonitorWrapper& monitor) {
return monitor.has_update();
}
std::unique_ptr<ValueWrapper> monitor_get_update(MonitorWrapper& monitor, double timeout) {
return monitor.get_update(timeout);
}
std::unique_ptr<ValueWrapper> monitor_try_get_update(MonitorWrapper& monitor) {
return monitor.try_get_update();
}
bool monitor_is_connected(const MonitorWrapper& monitor) {
return monitor.is_connected();
}
rust::String monitor_get_name(const MonitorWrapper& monitor) {
return monitor.name();
}
std::unique_ptr<ValueWrapper> monitor_pop(MonitorWrapper& monitor) {
return monitor.pop();
}
void MonitorBuilderWrapper::mask_connected(bool mask) {
mask_connected_ = mask;
}
void MonitorBuilderWrapper::mask_disconnected(bool mask) {
mask_disconnected_ = mask;
}
void MonitorBuilderWrapper::set_event_callback(void (*callback)()) {
rust_callback_ = callback;
}
std::unique_ptr<MonitorWrapper> MonitorBuilderWrapper::exec() {
try {
auto builder = context_.monitor(pv_name_)
.maskConnected(mask_connected_)
.maskDisconnected(mask_disconnected_);
auto connect = context_.connect(pv_name_).exec();
if (rust_callback_) {
auto callback_ptr = rust_callback_;
auto subscription = builder.event([callback_ptr](auto& subscription) {
callback_ptr();
}).exec();
auto wrapper = std::make_unique<MonitorWrapper>(
std::move(subscription), pv_name_, context_, rust_callback_, mask_connected_, mask_disconnected_);
wrapper->set_connect(std::move(connect));
return wrapper;
} else {
auto subscription = builder.exec();
auto wrapper = std::make_unique<MonitorWrapper>(
std::move(subscription), pv_name_, context_, nullptr, mask_connected_, mask_disconnected_);
wrapper->set_connect(std::move(connect));
return wrapper;
}
} catch (const std::exception& e) {
throw PvxsError(std::string("Error creating monitor for '") + pv_name_ + "': " + e.what());
}
}
std::unique_ptr<MonitorWrapper> MonitorBuilderWrapper::exec_with_callback(uint64_t callback_id) {
try {
callback_id_ = callback_id;
auto builder = context_.monitor(pv_name_)
.maskConnected(mask_connected_)
.maskDisconnected(mask_disconnected_);
auto subscription = builder.exec();
return std::make_unique<MonitorWrapper>(
std::move(subscription), pv_name_, context_);
} catch (const std::exception& e) {
throw PvxsError(std::string("Error creating monitor with callback for '") + pv_name_ + "': " + e.what());
}
}
std::unique_ptr<MonitorBuilderWrapper> context_monitor_builder_create(
ContextWrapper& ctx,
rust::String pv_name) {
return ctx.monitor_builder(std::string(pv_name));
}
void monitor_builder_mask_connected(MonitorBuilderWrapper& builder, bool mask) {
builder.mask_connected(mask);
}
void monitor_builder_mask_disconnected(MonitorBuilderWrapper& builder, bool mask) {
builder.mask_disconnected(mask);
}
void monitor_builder_set_event_callback(MonitorBuilderWrapper& builder, uintptr_t callback_ptr) {
auto rust_fn = reinterpret_cast<void(*)()>(callback_ptr);
builder.set_event_callback(rust_fn);
}
std::unique_ptr<MonitorWrapper> monitor_builder_exec(MonitorBuilderWrapper& builder) {
return builder.exec();
}
std::unique_ptr<MonitorWrapper> monitor_builder_exec_with_callback(
MonitorBuilderWrapper& builder,
uint64_t callback_id) {
return builder.exec_with_callback(callback_id);
}
}