36 #include <boost/algorithm/string.hpp>
39 #include <json/value.h>
42 #include <unordered_set>
47 inline void replaceLocalhostServers(Json::Value &nodes,
48 std::string
const &host) {
49 BOOST_ASSERT_MSG(host.length() > 0,
50 "Cannot replace localhost with an empty host name!");
51 const auto deviceElementTypeName =
52 common::elements::getTypeName<common::elements::DeviceElement>();
53 static const auto LOCALHOST =
"localhost";
54 for (
auto &node : nodes) {
55 if (node[
"type"].asString() == deviceElementTypeName) {
56 auto &serverRef = node[
"server"];
57 auto server = serverRef.asString();
59 auto it = server.find(LOCALHOST);
61 if (it != server.npos) {
75 serverRef = boost::algorithm::ireplace_first_copy(
83 static const std::chrono::milliseconds STARTUP_CONNECT_TIMEOUT(200);
84 static const std::chrono::milliseconds STARTUP_TREE_TIMEOUT(1000);
85 static const std::chrono::milliseconds STARTUP_LOOP_SLEEP(1);
87 PureClientContext::PureClientContext(
const char appId[],
const char host[],
88 common::ClientContextDeleter del)
90 m_ifaceMgr(m_pathTreeOwner, m_factory,
91 *static_cast<common::ClientContext *>(this)) {
93 if (!m_network.
isUp()) {
94 throw std::runtime_error(
"Network error: " + m_network.
getError());
98 populateRemoteHandlerFactory(m_factory, m_vrpnConns);
100 std::string sysDeviceName =
102 m_mainConn = m_vrpnConns.getConnection(
109 using DedupJsonFunction =
112 m_systemComponent->registerReplaceTreeHandler(
113 DedupJsonFunction([&](Json::Value nodes) {
114 logger()->debug(
"Got updated path tree, processing");
119 replaceLocalhostServers(nodes, m_host);
126 typedef std::chrono::system_clock clock;
127 auto begin = clock::now();
130 auto connEnd = begin + STARTUP_CONNECT_TIMEOUT;
131 while (clock::now() < connEnd && !m_gotConnection) {
133 std::this_thread::sleep_for(STARTUP_LOOP_SLEEP);
135 if (!m_gotConnection) {
137 <<
"Could not connect to OSVR server in the timeout period "
139 << std::chrono::duration_cast<std::chrono::milliseconds>(
140 STARTUP_CONNECT_TIMEOUT)
147 auto treeEnd = begin + STARTUP_TREE_TIMEOUT;
148 while (clock::now() < treeEnd && !m_pathTreeOwner) {
150 std::this_thread::sleep_for(STARTUP_LOOP_SLEEP);
152 auto timeToStartup = (clock::now() - begin);
156 logger()->log(m_pathTreeOwner ? util::log::LogLevel::info
157 : util::log::LogLevel::notice)
158 <<
"Connection process took "
159 << std::chrono::duration_cast<std::chrono::milliseconds>(
162 <<
"ms: " << (m_gotConnection ?
"have connection to server, "
163 :
"don't have connection to server, ")
164 << (m_pathTreeOwner ?
"have path tree" :
"don't have path tree");
167 PureClientContext::~PureClientContext() {}
169 void PureClientContext::m_update() {
171 m_vrpnConns.updateAll();
173 if (!m_gotConnection && m_mainConn->connected()) {
174 logger()->info(
"Got connection to main OSVR server");
175 m_gotConnection =
true;
179 m_systemDevice->update();
184 void PureClientContext::m_sendRoute(std::string
const &route) {
185 m_systemComponent->sendClientRouteUpdate(route);
189 void PureClientContext::m_handleNewInterface(
194 void PureClientContext::m_handleReleasingInterface(
196 m_ifaceMgr.releaseInterface(iface);
199 bool PureClientContext::m_getStatus()
const {
200 return m_gotConnection && m_pathTreeOwner;
203 common::PathTree
const &PureClientContext::m_getPathTree()
const {
204 return m_pathTreeOwner.
get();
207 common::Transform
const &
208 PureClientContext::m_getRoomToWorldTransform()
const {
209 return m_roomToWorld;
212 void PureClientContext::m_setRoomToWorldTransform(
213 common::Transform
const &xform) {
214 m_roomToWorld = xform;
void replaceTree(Json::Value const &nodes)
Replace the entirety of the path tree from the given serialized array of nodes.
shared_ptr< ClientInterface > ClientInterfacePtr
Pointer for holding ClientInterface objects safely.
BaseDevicePtr createClientDevice(std::string const &name, vrpn_ConnectionPtr const &conn)
Factory function for a bare client device with no components/interfaces registered by default...
Header including PathTree.h and all additional headers needed to define related types.
std::string const & getError() const
Get error message, if any.
static shared_ptr< SystemComponent > create()
Factory method.
void addInterface(common::ClientInterfacePtr const &iface, bool verboseFailure=true)
Internal, configured header file for verbosity macros.
static const char * deviceName()
Get the special device name to be used with this component.
osvr::util::log::LoggerPtr const & logger() const
Provides logger access for related internal classes.
void updateHandlers()
run update on all remote handlers
A wrapper for a unary function that only calls its contained function when the input has changed...
bool isUp() const
Get whether the networking system is successfully "up".
PathTree & get()
Access the path tree object itself.