From 7cca96dcfb281c24d6a0c8819d3357a87b912c1c Mon Sep 17 00:00:00 2001 From: Thomas Stoddard Date: Fri, 8 May 2026 17:28:49 +0000 Subject: [PATCH] All: Switch to Servd default on See README for details on how to install Servd. --- README.md | 8 ++++++++ api/icsneocpp/event.cpp | 6 ++++++ bindings/python/icsneopy/api/event.cpp | 2 ++ include/icsneo/api/event.h | 2 ++ platform/servd.cpp | 15 ++++++++++++--- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f1abbfdd..460961f5 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,14 @@ libicsneo is the [Intrepid Control Systems](https://intrepidcs.com/) device communication library. Installation and usage documentation can be found within each of the respective APIs. +## Installation + +libicsneo relies on Servd, IntrepidCS's device communication server. + +Servd can be installed for all platforms from https://cdn.intrepidcs.net/servd/. + +Instructions for installing each API can be found in its respective documentation. + ## Documentation - [C++](https://libicsneo.readthedocs.io/en/latest/icsneocpp/) diff --git a/api/icsneocpp/event.cpp b/api/icsneocpp/event.cpp index 3edb6c89..dc7604ea 100644 --- a/api/icsneocpp/event.cpp +++ b/api/icsneocpp/event.cpp @@ -166,6 +166,8 @@ static constexpr const char* SERVD_RECV_ERROR = "Error receiving from Servd"; static constexpr const char* SERVD_POLL_ERROR = "Error polling on Servd socket"; static constexpr const char* SERVD_NODATA_ERROR = "No data received from Servd"; static constexpr const char* SERVD_JOIN_MULTICAST_ERROR = "Error joining Servd multicast group"; +static constexpr const char* SERVD_NOT_REACHABLE = "Could not reach Servd; ensure it is installed and running"; +static constexpr const char* SERVD_NO_DEVICES_FOUND = "Servd is running but no devices found"; // DXX static constexpr const char* DXX_ERROR_SYS = "System error, check errno/GetLastError()"; @@ -438,6 +440,10 @@ const char* APIEvent::DescriptionForType(Type type) { return SERVD_NODATA_ERROR; case Type::ServdJoinMulticastError: return SERVD_JOIN_MULTICAST_ERROR; + case Type::ServdNotReachable: + return SERVD_NOT_REACHABLE; + case Type::ServdNoDevicesFound: + return SERVD_NO_DEVICES_FOUND; // DXX case Type::DXXErrorSys: diff --git a/bindings/python/icsneopy/api/event.cpp b/bindings/python/icsneopy/api/event.cpp index f27b4511..919e1a2c 100644 --- a/bindings/python/icsneopy/api/event.cpp +++ b/bindings/python/icsneopy/api/event.cpp @@ -126,6 +126,8 @@ void init_event(pybind11::module_& m) { .value("ServdPollError", APIEvent::Type::ServdPollError) .value("ServdNoDataError", APIEvent::Type::ServdNoDataError) .value("ServdJoinMulticastError", APIEvent::Type::ServdJoinMulticastError) + .value("ServdNotReachable", APIEvent::Type::ServdNotReachable) + .value("ServdNoDevicesFound", APIEvent::Type::ServdNoDevicesFound) .value("DXXErrorSys", APIEvent::Type::DXXErrorSys) .value("DXXErrorInt", APIEvent::Type::DXXErrorInt) .value("DXXErrorOverflow", APIEvent::Type::DXXErrorOverflow) diff --git a/include/icsneo/api/event.h b/include/icsneo/api/event.h index 29a2839c..9db3cd12 100644 --- a/include/icsneo/api/event.h +++ b/include/icsneo/api/event.h @@ -165,6 +165,8 @@ public: ServdPollError = ServdBindError + 8, ServdNoDataError = ServdBindError + 9, ServdJoinMulticastError = ServdBindError + 10, + ServdNotReachable = ServdBindError + 11, + ServdNoDevicesFound = ServdBindError + 12, // DXX DXXErrorSys = 0x6100, diff --git a/platform/servd.cpp b/platform/servd.cpp index 4b1786ff..ec2f6169 100644 --- a/platform/servd.cpp +++ b/platform/servd.cpp @@ -20,7 +20,7 @@ bool Servd::Enabled() { #ifdef _MSC_VER #pragma warning(pop) #endif - return enabled ? enabled[0] == '1' : false; + return enabled ? enabled[0] == '1' : true; } std::vector split(const std::string_view& str, char delim = ' ') { @@ -52,7 +52,7 @@ void Servd::Find(std::vector& found) { response.resize(512); const std::string version_request = SERVD_VERSION_STR + " version"; if(!socket.transceive(version_request, response, std::chrono::milliseconds(5000))) { - EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error); + EventManager::GetInstance().add(APIEvent::Type::ServdNotReachable, APIEvent::Severity::Error); return; } @@ -67,11 +67,16 @@ void Servd::Find(std::vector& found) { EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error); return; } + const size_t preCount = found.size(); + bool parseError = false; const auto lines = split(response, '\n'); for(auto&& line : lines) { const auto cols = split(line, ' '); if(cols.size() < 3) { - EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error); + if(!line.empty()) { + EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error); + parseError = true; + } continue; } const auto& serial = cols[0]; @@ -81,6 +86,7 @@ void Servd::Find(std::vector& found) { port = static_cast(std::stoi(cols[2])); } catch (const std::exception&) { EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error); + parseError = true; continue; } Address address(ip.c_str(), port); @@ -90,6 +96,9 @@ void Servd::Find(std::vector& found) { return std::make_unique(err, forDevice, address); }; } + if(!parseError && found.size() == preCount) { + EventManager::GetInstance().add(APIEvent::Type::ServdNoDevicesFound, APIEvent::Severity::EventInfo); + } } Servd::Servd(const device_eventhandler_t& err, neodevice_t& forDevice, const Address& address) :