Files
ANSCORE/integrations/ANSIO/dllmain.cpp

1142 lines
42 KiB
C++
Raw Normal View History

2026-03-28 16:54:11 +11:00
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "iobox_api.h"
#include <cstdint>
#include <memory>
#include <unordered_map>
#include <condition_variable>
#include <mutex>
// Handle registry with refcount — prevents use-after-free when
// ReleaseANSIOHandle is called while an operation is still running.
static std::unordered_map<ANSCENTER::iobox_api*, int>& IOHandleRegistry() {
static std::unordered_map<ANSCENTER::iobox_api*, int> s;
return s;
}
static std::mutex& IOHandleRegistryMutex() {
static std::mutex m;
return m;
}
static std::condition_variable& IOHandleRegistryCV() {
static std::condition_variable cv;
return cv;
}
static void RegisterIOHandle(ANSCENTER::iobox_api* h) {
std::lock_guard<std::mutex> lk(IOHandleRegistryMutex());
IOHandleRegistry()[h] = 1;
}
static ANSCENTER::iobox_api* AcquireIOHandle(ANSCENTER::iobox_api* h) {
std::lock_guard<std::mutex> lk(IOHandleRegistryMutex());
auto it = IOHandleRegistry().find(h);
if (it == IOHandleRegistry().end()) return nullptr;
it->second++;
return h;
}
static bool ReleaseIOHandleRef(ANSCENTER::iobox_api* h) {
std::lock_guard<std::mutex> lk(IOHandleRegistryMutex());
auto it = IOHandleRegistry().find(h);
if (it == IOHandleRegistry().end()) return false;
it->second--;
if (it->second <= 0) {
IOHandleRegistry().erase(it);
IOHandleRegistryCV().notify_all();
return true;
}
return false;
}
static bool UnregisterIOHandle(ANSCENTER::iobox_api* h) {
std::unique_lock<std::mutex> lk(IOHandleRegistryMutex());
auto it = IOHandleRegistry().find(h);
if (it == IOHandleRegistry().end()) return false;
it->second--;
bool ok = IOHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() {
auto it2 = IOHandleRegistry().find(h);
return it2 == IOHandleRegistry().end() || it2->second <= 0;
});
if (!ok) {
OutputDebugStringA("WARNING: UnregisterIOHandle timed out waiting for in-flight operations\n");
}
IOHandleRegistry().erase(h);
return true;
}
// RAII guard — ensures ReleaseIOHandleRef is always called
class IOHandleGuard {
ANSCENTER::iobox_api* engine;
public:
explicit IOHandleGuard(ANSCENTER::iobox_api* e) : engine(e) {}
~IOHandleGuard() { if (engine) ReleaseIOHandleRef(engine); }
ANSCENTER::iobox_api* get() const { return engine; }
explicit operator bool() const { return engine != nullptr; }
IOHandleGuard(const IOHandleGuard&) = delete;
IOHandleGuard& operator=(const IOHandleGuard&) = delete;
};
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
) noexcept
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// Helper: safely copy a std::string into a LabVIEW LStrHandle.
// Returns 1 on success, 0 on failure (empty string or allocation error).
static int CopyToLStrHandle(LStrHandle handle, const std::string& str) noexcept {
if (str.empty() || handle == nullptr) return 0;
const auto size = static_cast<int32>(str.length());
MgErr error = DSSetHandleSize(handle, sizeof(int32) + size * sizeof(uChar));
if (error != noErr) return 0;
(*handle)->cnt = size;
memcpy((*handle)->str, str.c_str(), static_cast<size_t>(size));
return 1;
}
// Helper: join a vector of strings with semicolon separator.
static std::string JoinStrings(const std::vector<std::string>& items) {
std::string result;
for (size_t i = 0; i < items.size(); ++i) {
if (i > 0) result += ";";
result += items[i];
}
return result;
}
extern "C" ANSIO_API int CreateANSIOHandle(ANSCENTER::iobox_api** Handle, const char* multicastIPAddress, int multicastPort) {
if (Handle == nullptr || multicastIPAddress == nullptr) return 0;
try {
// Release existing handle if called twice (prevents leak from LabVIEW)
if (*Handle) {
if (UnregisterIOHandle(*Handle)) {
delete *Handle;
}
*Handle = nullptr;
}
// std::unique_ptr ensures automatic cleanup on any failure path
auto ptr = std::make_unique<ANSCENTER::iobox_api>(multicastIPAddress, multicastPort);
// Transfer ownership to caller on success
*Handle = ptr.release();
RegisterIOHandle(*Handle);
return 1;
}
catch (const std::exception&) {
if (Handle) *Handle = nullptr;
return 0;
}
catch (...) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" ANSIO_API int ConnectANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int ioBoxPort, const char* userName, const char* passWord, LStrHandle deviceStr) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
return CopyToLStrHandle(deviceStr, guard.get()->connectToIobox(ioBoxIP, ioBoxPort, userName, passWord));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int AdvancedConnectANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int ioBoxPort, const char* ioBoxSN, const char* userName, const char* passWord, LStrHandle deviceStr) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || ioBoxSN == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
std::vector<std::string> st = guard.get()->advancedConnectToIobox(ioBoxIP, ioBoxPort, ioBoxSN, userName, passWord);
if (st.empty()) return 0;
return CopyToLStrHandle(deviceStr, JoinStrings(st));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int DisconnectANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
return guard.get()->disconnectToIoboxWithResetOutputs(ioBoxIP) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
static int ReleaseANSIOHandle_Impl(ANSCENTER::iobox_api** Handle) {
try {
if (!Handle || !*Handle) return 1;
if (!UnregisterIOHandle(*Handle)) {
*Handle = nullptr;
return 1;
}
delete *Handle;
*Handle = nullptr;
return 1;
}
catch (...) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" ANSIO_API int ReleaseANSIOHandle(ANSCENTER::iobox_api** Handle)
{
__try {
return ReleaseANSIOHandle_Impl(Handle);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" ANSIO_API int SetValueANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, const char* value) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr || value == nullptr) return 0;
try {
return guard.get()->setValue(ioBoxIP, channelName, value) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int GetValueANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, LStrHandle lStrValue) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr) return 0;
try {
std::string st = "fail";
bool success = guard.get()->getValue(ioBoxIP, channelName, st);
if (!success || st.empty() || st == "fail") return 0;
return CopyToLStrHandle(lStrValue, st);
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int SetAuthenticationANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* userName, const char* passWord) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
return guard.get()->setAuthenticationIobox(ioBoxIP, userName, passWord) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ScanANSIOHandle(ANSCENTER::iobox_api** Handle, int timeout, LStrHandle ipAddresses) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->scanNetworkDevicesMulticast(timeout);
if (st.empty()) return 0;
return CopyToLStrHandle(ipAddresses, JoinStrings(st));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ScanANSIOUnicastHandle(ANSCENTER::iobox_api** Handle, int timeout, LStrHandle ipAddresses) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->scanNetworkDevicesManually(timeout);
if (st.empty()) return 0;
return CopyToLStrHandle(ipAddresses, JoinStrings(st));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int AdvancedScanANSIOHandle(ANSCENTER::iobox_api** Handle, int timeout, LStrHandle deviceInfos) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->advancedScan(timeout);
if (st.empty()) return 0;
return CopyToLStrHandle(deviceInfos, JoinStrings(st));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int AdvancedStaticScanANSIOHandle(int timeout, LStrHandle deviceInfos) {
try {
ANSCENTER::iobox_api iobox_api("239.255.255.250", 12345);
std::vector<std::string> st = iobox_api.advancedScan(timeout);
if (st.empty()) return 0;
return CopyToLStrHandle(deviceInfos, JoinStrings(st));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ScanANSIOHandle_CPP(ANSCENTER::iobox_api** Handle, int timeout, std::string& ipAddresses) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->scanNetworkDevicesMulticast(timeout);
if (st.empty()) return 0;
ipAddresses = JoinStrings(st);
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ScanANSIOUnicastHandle_CPP(ANSCENTER::iobox_api** Handle, int timeout, std::string& ipAddresses) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->scanNetworkDevicesManually(timeout);
if (st.empty()) return 0;
ipAddresses = JoinStrings(st);
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int AdvancedScanANSIOHandle_CPP(ANSCENTER::iobox_api** Handle, int timeout, std::string& deviceInfos) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->advancedScan(timeout);
if (st.empty()) return 0;
deviceInfos = JoinStrings(st);
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int AdvancedStaticScanANSIOHandle_CPP(int timeout, std::string& deviceInfos)
{
try {
ANSCENTER::iobox_api iobox_api("239.255.255.250", 12345);
std::vector<std::string> st = iobox_api.advancedScan(timeout);
if (st.empty()) return 0;
deviceInfos = JoinStrings(st);
if (deviceInfos.empty()) return 0;
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int GetChannelNamesANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int timeout, LStrHandle channelNames) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->getDeviceChannelNames(ioBoxIP);
if (st.empty()) return 0;
return CopyToLStrHandle(channelNames, JoinStrings(st));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int GetValueANSIOHandle_CPP(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, std::string& lStrValue) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr) return 0;
try {
std::string st = "fail";
bool success = guard.get()->getValue(ioBoxIP, channelName, st);
if (!success || st.empty() || st == "fail") return 0;
lStrValue = st;
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int GetChannelNamesANSIOHandle_CPP(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int timeout, std::string& channelNames) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->getDeviceChannelNames(ioBoxIP);
if (st.empty()) return 0;
channelNames = JoinStrings(st);
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ResetAuthenticationANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* token) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || token == nullptr) return 0;
try {
return guard.get()->resetAuthenticationIobox(ioBoxIP, token) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ResetANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* token) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || token == nullptr) return 0;
try {
return guard.get()->resetIobox(ioBoxIP, token) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int GenerateANSIOTokenHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, LStrHandle tokenStr) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
return CopyToLStrHandle(tokenStr, guard.get()->generateToken(ioBoxIP));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int GenerateANSIOTokenHandle_CPP(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, std::string& tokenStr) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::string st = guard.get()->generateToken(ioBoxIP);
if (st.empty()) return 0;
tokenStr = st;
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ConnectANSIOHandle_CPP(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int ioBoxPort, const char* userName, const char* passWord, std::string& deviceStr) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
std::string st = guard.get()->connectToIobox(ioBoxIP, ioBoxPort, userName, passWord);
if (st.empty()) return 0;
deviceStr = st;
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int AdvancedConnectANSIOHandle_CPP(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int ioBoxPort, const char* ioBoxSN, const char* userName, const char* passWord, std::string& deviceStr) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || ioBoxSN == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
std::vector<std::string> st = guard.get()->advancedConnectToIobox(ioBoxIP, ioBoxPort, ioBoxSN, userName, passWord);
if (st.empty()) return 0;
deviceStr = JoinStrings(st);
return 1;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int CheckANSIOStatusHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
return guard.get()->checkTcpConnectStatus(ioBoxIP) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int OpenANSAIRS232Port(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int baudrate, int DataBits, int stopBits, int parityBits) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
return guard.get()->openRs232Port(ioBoxIP, baudrate, DataBits, stopBits, parityBits) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int CloseANSAIRS232Port(ANSCENTER::iobox_api** Handle, const char* ioBoxIP) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
return guard.get()->closeRs232Port(ioBoxIP) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int WriteANSAIRS232Port(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* data, int timeout_ms) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || data == nullptr) return 0;
try {
return guard.get()->writeRs232Port(ioBoxIP, data, timeout_ms) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ReadANSAIRS232Port(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* terminatorString, int lenExpect, int timeout_ms, LStrHandle receivedData) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
const char* safeTerminator = (terminatorString != nullptr) ? terminatorString : "";
return CopyToLStrHandle(receivedData, guard.get()->readRs232Port(ioBoxIP, safeTerminator, lenExpect, timeout_ms));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
// OTA
extern "C" ANSIO_API int OTAANSIOFirmwareDevice(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* filename, const char* type) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || filename == nullptr || type == nullptr) return 0;
try {
return guard.get()->otaFirmwareDevice(ioBoxIP, filename, type) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
// Synchronous version (existing behavior)
extern "C" ANSIO_API int ToggleIoboxHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, int timeOut, int revertFlag, int resetFlag) {
try {
// Input validation
if (Handle == nullptr || *Handle == nullptr) {
return -1; // Invalid handle
}
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return -1;
if (ioBoxIP == nullptr || channelName == nullptr) {
return -2; // Invalid parameters
}
if (timeOut < 0) {
return -3; // Invalid timeout
}
// Convert C parameters to C++ types
std::string remote(ioBoxIP);
std::string channel(channelName);
bool revert = (revertFlag != 0);
bool reset = (resetFlag != 0);
// Call synchronous version (asyncMode = false)
bool result = guard.get()->toggleIobox(remote, channel, timeOut, revert, reset, false);
return result ? 1 : 0;
}
catch (const std::exception&) {
return -4; // Exception occurred
}
catch (...) {
return -5; // Unknown exception
}
}
// Asynchronous version (new function)
extern "C" ANSIO_API int ToggleIoboxHandleAsync(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, int timeOut, int revertFlag, int resetFlag) {
try {
// Input validation
if (Handle == nullptr || *Handle == nullptr) {
return -1; // Invalid handle
}
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return -1;
if (ioBoxIP == nullptr || channelName == nullptr) {
return -2; // Invalid parameters
}
if (timeOut < 0) {
return -3; // Invalid timeout
}
// Convert C parameters to C++ types
std::string remote(ioBoxIP);
std::string channel(channelName);
bool revert = (revertFlag != 0);
bool reset = (resetFlag != 0);
// Call asynchronous version (asyncMode = true)
bool result = guard.get()->toggleIobox(remote, channel, timeOut, revert, reset, true);
return result ? 1 : 0; // Returns immediately
}
catch (const std::exception&) {
return -4; // Exception occurred
}
catch (...) {
return -5; // Unknown exception
}
}
extern "C" ANSIO_API int GetStaticIpConfigANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, LStrHandle staticIpConfigInfo) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
try {
std::vector<std::string> configs = guard.get()->getStaticIpConfig(ioBoxIP);
if (configs.empty()) return 0;
return CopyToLStrHandle(staticIpConfigInfo, JoinStrings(configs));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int SetStaticIpConfigANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, int enable, const char* ip, const char* gw, const char* nm) {
if (Handle == nullptr || *Handle == nullptr || ioBoxIP == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ip == nullptr || gw == nullptr || nm == nullptr) return 0;
try {
return guard.get()->setStaticIpConfig(ioBoxIP, enable != 0, ip, gw, nm) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int GetValueDataStringIoboxFromChannelNameANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, LStrHandle dataValue) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr) return 0;
try {
return CopyToLStrHandle(dataValue, guard.get()->getValueDataStringIoboxFromChannelName(ioBoxIP, channelName));
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int ToggleDigitalOutputANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, int milliseconds, int invertFlag, int resetFlag) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr) return 0;
try {
return guard.get()->toggleDigitalOutput(ioBoxIP, channelName, std::to_string(milliseconds), invertFlag != 0, resetFlag != 0) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" ANSIO_API int SetAIBValueDataStringIoboxFromChannelNameANSIOHandle(ANSCENTER::iobox_api** Handle, const char* ioBoxIP, const char* channelName, const char* value) {
if (Handle == nullptr || *Handle == nullptr) return 0;
IOHandleGuard guard(AcquireIOHandle(*Handle));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr || value == nullptr) return 0;
try {
return guard.get()->setAIBValueDataStringIoboxFromChannelName(ioBoxIP, channelName, value) ? 1 : 0;
}
catch (const std::exception&) {
return 0;
}
catch (...) {
return 0;
}
}
// ============================================================================
// V2 API — handle passed by value (uint64_t) to avoid LabVIEW buffer reuse bug
// ============================================================================
extern "C" ANSIO_API int ConnectANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, int ioBoxPort, const char* userName, const char* passWord, LStrHandle deviceStr) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
return CopyToLStrHandle(deviceStr, guard.get()->connectToIobox(ioBoxIP, ioBoxPort, userName, passWord));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int AdvancedConnectANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, int ioBoxPort, const char* ioBoxSN, const char* userName, const char* passWord, LStrHandle deviceStr) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || ioBoxSN == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
std::vector<std::string> st = guard.get()->advancedConnectToIobox(ioBoxIP, ioBoxPort, ioBoxSN, userName, passWord);
if (st.empty()) return 0;
return CopyToLStrHandle(deviceStr, JoinStrings(st));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int DisconnectANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
return guard.get()->disconnectToIoboxWithResetOutputs(ioBoxIP) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int CheckANSIOStatusHandle_V2(uint64_t handleVal, const char* ioBoxIP) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
return guard.get()->checkTcpConnectStatus(ioBoxIP) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int SetValueANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* channelName, const char* value) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr || value == nullptr) return 0;
try {
return guard.get()->setValue(ioBoxIP, channelName, value) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int GetValueANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* channelName, LStrHandle lStrValue) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr) return 0;
try {
std::string st = "fail";
bool success = guard.get()->getValue(ioBoxIP, channelName, st);
if (!success || st.empty() || st == "fail") return 0;
return CopyToLStrHandle(lStrValue, st);
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int GetValueDataStringIoboxFromChannelNameANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* channelName, LStrHandle dataValue) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr) return 0;
try {
return CopyToLStrHandle(dataValue, guard.get()->getValueDataStringIoboxFromChannelName(ioBoxIP, channelName));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int SetAIBValueDataStringIoboxFromChannelNameANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* channelName, const char* value) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr || value == nullptr) return 0;
try {
return guard.get()->setAIBValueDataStringIoboxFromChannelName(ioBoxIP, channelName, value) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int SetAuthenticationANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* userName, const char* passWord) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || userName == nullptr || passWord == nullptr) return 0;
try {
return guard.get()->setAuthenticationIobox(ioBoxIP, userName, passWord) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int ResetAuthenticationANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* token) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || token == nullptr) return 0;
try {
return guard.get()->resetAuthenticationIobox(ioBoxIP, token) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int GenerateANSIOTokenHandle_V2(uint64_t handleVal, const char* ioBoxIP, LStrHandle tokenStr) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
return CopyToLStrHandle(tokenStr, guard.get()->generateToken(ioBoxIP));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int ScanANSIOHandle_V2(uint64_t handleVal, int timeout, LStrHandle ipAddresses) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->scanNetworkDevicesMulticast(timeout);
if (st.empty()) return 0;
return CopyToLStrHandle(ipAddresses, JoinStrings(st));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int ScanANSIOUnicastHandle_V2(uint64_t handleVal, int timeout, LStrHandle ipAddresses) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->scanNetworkDevicesManually(timeout);
if (st.empty()) return 0;
return CopyToLStrHandle(ipAddresses, JoinStrings(st));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int AdvancedScanANSIOHandle_V2(uint64_t handleVal, int timeout, LStrHandle deviceInfos) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
try {
std::vector<std::string> st = guard.get()->advancedScan(timeout);
if (st.empty()) return 0;
return CopyToLStrHandle(deviceInfos, JoinStrings(st));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int GetChannelNamesANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, int timeout, LStrHandle channelNames) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
std::vector<std::string> st = guard.get()->getDeviceChannelNames(ioBoxIP);
if (st.empty()) return 0;
return CopyToLStrHandle(channelNames, JoinStrings(st));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int ResetANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* token) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || token == nullptr) return 0;
try {
return guard.get()->resetIobox(ioBoxIP, token) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int ToggleIoboxHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* channelName, int timeOut, int revertFlag, int resetFlag) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return -1;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return -1;
if (ioBoxIP == nullptr || channelName == nullptr) return -2;
if (timeOut < 0) return -3;
try {
std::string remote(ioBoxIP);
std::string channel(channelName);
bool revert = (revertFlag != 0);
bool reset = (resetFlag != 0);
bool result = guard.get()->toggleIobox(remote, channel, timeOut, revert, reset, false);
return result ? 1 : 0;
}
catch (const std::exception&) { return -4; }
catch (...) { return -5; }
}
extern "C" ANSIO_API int ToggleIoboxHandleAsync_V2(uint64_t handleVal, const char* ioBoxIP, const char* channelName, int timeOut, int revertFlag, int resetFlag) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return -1;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return -1;
if (ioBoxIP == nullptr || channelName == nullptr) return -2;
if (timeOut < 0) return -3;
try {
std::string remote(ioBoxIP);
std::string channel(channelName);
bool revert = (revertFlag != 0);
bool reset = (resetFlag != 0);
bool result = guard.get()->toggleIobox(remote, channel, timeOut, revert, reset, true);
return result ? 1 : 0;
}
catch (const std::exception&) { return -4; }
catch (...) { return -5; }
}
extern "C" ANSIO_API int ToggleDigitalOutputANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, const char* channelName, int milliseconds, int invertFlag, int resetFlag) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || channelName == nullptr) return 0;
try {
return guard.get()->toggleDigitalOutput(ioBoxIP, channelName, std::to_string(milliseconds), invertFlag != 0, resetFlag != 0) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int OpenANSAIRS232Port_V2(uint64_t handleVal, const char* ioBoxIP, int baudrate, int DataBits, int stopBits, int parityBits) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
return guard.get()->openRs232Port(ioBoxIP, baudrate, DataBits, stopBits, parityBits) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int CloseANSAIRS232Port_V2(uint64_t handleVal, const char* ioBoxIP) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
return guard.get()->closeRs232Port(ioBoxIP) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int WriteANSAIRS232Port_V2(uint64_t handleVal, const char* ioBoxIP, const char* data, int timeout_ms) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || data == nullptr) return 0;
try {
return guard.get()->writeRs232Port(ioBoxIP, data, timeout_ms) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int ReadANSAIRS232Port_V2(uint64_t handleVal, const char* ioBoxIP, const char* terminatorString, int lenExpect, int timeout_ms, LStrHandle receivedData) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
const char* safeTerminator = (terminatorString != nullptr) ? terminatorString : "";
return CopyToLStrHandle(receivedData, guard.get()->readRs232Port(ioBoxIP, safeTerminator, lenExpect, timeout_ms));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int GetStaticIpConfigANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, LStrHandle staticIpConfigInfo) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr) return 0;
try {
std::vector<std::string> configs = guard.get()->getStaticIpConfig(ioBoxIP);
if (configs.empty()) return 0;
return CopyToLStrHandle(staticIpConfigInfo, JoinStrings(configs));
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int SetStaticIpConfigANSIOHandle_V2(uint64_t handleVal, const char* ioBoxIP, int enable, const char* ip, const char* gw, const char* nm) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || ip == nullptr || gw == nullptr || nm == nullptr) return 0;
try {
return guard.get()->setStaticIpConfig(ioBoxIP, enable != 0, ip, gw, nm) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
extern "C" ANSIO_API int OTAANSIOFirmwareDevice_V2(uint64_t handleVal, const char* ioBoxIP, const char* filename, const char* type) {
auto* _v2h = reinterpret_cast<ANSCENTER::iobox_api*>(handleVal); if (!_v2h) return 0;
IOHandleGuard guard(AcquireIOHandle(_v2h));
if (!guard) return 0;
if (ioBoxIP == nullptr || filename == nullptr || type == nullptr) return 0;
try {
return guard.get()->otaFirmwareDevice(ioBoxIP, filename, type) ? 1 : 0;
}
catch (const std::exception&) { return 0; }
catch (...) { return 0; }
}
// End of ANSIO/dllmain.cpp