Skip to content

Commit c3c02ea

Browse files
Merge remote-tracking branch 'origin/master'
2 parents 3c4a3d1 + aabc918 commit c3c02ea

30 files changed

Lines changed: 510 additions & 324 deletions

share/covise/demo/demos.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@
549549
"description": "",
550550
"headline": "Magnetgetriebe",
551551
"id": 74,
552-
"image": "",
552+
"image": "Magnetgetriebe.png",
553553
"launch": [
554554
{
555555
"args": [
@@ -560,7 +560,7 @@
560560
}
561561
],
562562
"tags": [
563-
"broken"
563+
"electromagnetics"
564564
]
565565
},
566566
{

src/OpenCOVER/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ if (COVISE_USE_VIRVO)
126126
endif()
127127
ADD_SUBDIRECTORY(OpenVRUI)
128128
ADD_SUBDIRECTORY(PluginUtil)
129+
ADD_SUBDIRECTORY(DataClient)
129130
ADD_SUBDIRECTORY(OpcUaClient)
130131
ADD_SUBDIRECTORY(HTTPClient)
131132
ADD_SUBDIRECTORY(cover)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
SET(HEADERS
3+
DataClient.h
4+
MultiDimensionalArray.h
5+
ObserverHandle.h
6+
)
7+
8+
SET(SOURCES
9+
DataClient.cpp
10+
MultiDimensionalArray.cpp
11+
ObserverHandle.cpp
12+
)
13+
14+
ADD_COVISE_LIBRARY(coDataClient)
15+
target_link_libraries(coDataClient coOpenCOVER)
16+
COVISE_INSTALL_TARGET(coDataClient)
17+
COVISE_INSTALL_HEADERS(coDataClient ${HEADERS})
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include "DataClient.h"
2+
#include <cover/coVRMSController.h>
3+
4+
using namespace opencover::dataclient;
5+
6+
const char *opencover::dataclient::NoNodeName = "None";
7+
8+
void Client::queueUnregisterNode(size_t id)
9+
{
10+
std::lock_guard<std::mutex> lock(m_mutex);
11+
m_nodesToUnregister.push_back(id);
12+
}
13+
14+
bool isNumerical(std::type_index t)
15+
{
16+
return t == typeid(int8_t) || t == typeid(uint8_t) || t == typeid(int16_t) || t == typeid(uint16_t) || t == typeid(int32_t) || t == typeid(uint32_t) || t == typeid(double);
17+
}
18+
19+
std::vector<std::string> Client::allAvailableScalars() const
20+
{
21+
return getNodesWith(false, true);
22+
}
23+
24+
std::vector<std::string> Client::availableNumericalScalars() const
25+
{
26+
return getNodesWith(true, true);
27+
}
28+
29+
std::vector<std::string> Client::allAvailableArrays() const
30+
{
31+
return getNodesWith(false, false);
32+
}
33+
34+
std::vector<std::string> Client::availableNumericalArrays() const
35+
{
36+
return getNodesWith(true, false);
37+
}
38+
39+
auto msController = opencover::coVRMSController::instance();
40+
41+
Client::StatusChange Client::statusChanged(void* caller)
42+
{
43+
std::lock_guard<std::mutex> lock(m_mutex);
44+
StatusChange retval = Unchanged;
45+
if(msController->isMaster())
46+
{
47+
auto obs = m_statusObservers.find(caller);
48+
if(obs == m_statusObservers.end())
49+
{
50+
obs = m_statusObservers.insert(obs, std::make_pair(caller, false));
51+
}
52+
if(!obs->second)
53+
{
54+
obs->second = true;
55+
retval = isConnected() ? Connected : Disconnected;
56+
}
57+
}
58+
msController->syncData(&retval, sizeof(StatusChange));
59+
return retval;
60+
}
61+
62+
void Client::statusChanged()
63+
{
64+
std::lock_guard<std::mutex> lock(m_mutex);
65+
for(auto &obs : m_statusObservers)
66+
obs.second = false;
67+
}
68+
69+
Client** Client::getClientReference(const ObserverHandle &handle)
70+
{
71+
return &handle.m_deleter->m_client;
72+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#ifndef OPENCOVER_DATACLIENT_H
2+
#define OPENCOVER_DATACLIENT_H
3+
4+
#include "export.h"
5+
#include "MultiDimensionalArray.h"
6+
#include "ObserverHandle.h"
7+
8+
#include <cstdint>
9+
#include <functional>
10+
#include <memory>
11+
#include <string>
12+
#include <typeindex>
13+
#include <typeinfo>
14+
#include <vector>
15+
#include <mutex>
16+
17+
namespace opencover { namespace dataclient {
18+
19+
extern DATACLIENTEXPORT const char *NoNodeName;
20+
21+
class DATACLIENTEXPORT Client {
22+
public:
23+
virtual ~Client() = default;
24+
25+
// Connection lifecycle
26+
virtual void connect() = 0;
27+
virtual void disconnect() = 0;
28+
virtual bool isConnected() const = 0;
29+
enum StatusChange{ Unchanged, Connected, Disconnected};
30+
StatusChange statusChanged(void* caller);
31+
32+
33+
//get the available data nodes from the server
34+
std::vector<std::string> allAvailableScalars() const;
35+
std::vector<std::string> availableNumericalScalars() const;
36+
template<typename T>
37+
std::vector<std::string> availableScalars() const
38+
{
39+
return getNodesWith(std::type_index(typeid(T)), true);
40+
}
41+
std::vector<std::string> allAvailableArrays() const;
42+
std::vector<std::string> availableNumericalArrays() const;
43+
template<typename T>
44+
std::vector<std::string> availableArrays() const
45+
{
46+
return getNodesWith(std::type_index(typeid(T)), false);
47+
}
48+
49+
50+
//register nodes to get updates pushed by the server
51+
//keep the ObserverHandle as long as you want to observe
52+
virtual [[nodiscard]] ObserverHandle observeNode(const std::string &name) = 0;
53+
54+
// Pull-style access
55+
virtual double getNumericScalar(const std::string &name, double *timestep = nullptr) = 0;
56+
virtual double getNumericScalar(const ObserverHandle &handle, double *timestep = nullptr) = 0;
57+
58+
virtual size_t numNodeUpdates(const std::string &name) = 0;
59+
template<typename T>
60+
MultiDimensionalArray<T> getArray(const std::string &name)
61+
{
62+
auto p = getArrayImpl(std::type_index(typeid(T)), name);
63+
if (!p) return MultiDimensionalArray<T>{};
64+
if (auto casted = dynamic_cast<MultiDimensionalArray<T>*>(p.get())) {
65+
return *casted; // copies the MultiDimensionalArray<T> contents
66+
}
67+
return MultiDimensionalArray<T>{};
68+
}
69+
70+
//called by ObserverHandle
71+
void queueUnregisterNode(size_t id);
72+
73+
protected:
74+
void statusChanged();
75+
Client** getClientReference(const ObserverHandle &handle);
76+
private:
77+
78+
virtual std::unique_ptr<detail::MultiDimensionalArrayBase> getArrayImpl(std::type_index type, const std::string &name) = 0;
79+
virtual std::vector<std::string> getNodesWith(std::type_index type, bool isScalar) const = 0;
80+
virtual std::vector<std::string> getNodesWith(bool isArithmetic, bool isScalar) const = 0;
81+
std::mutex m_mutex;
82+
std::vector<size_t> m_nodesToUnregister;
83+
std::map<void*, bool> m_statusObservers; //stores which objects received a changed status
84+
bool m_connected = false;
85+
};
86+
87+
}} // namespace
88+
89+
#endif // OPENCOVER_DATACLIENT_H
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include "MultiDimensionalArray.h"
2+
3+
using namespace opencover::dataclient;
4+
5+
bool detail::MultiDimensionalArrayBase::isScalar() const {return dimensions.size() == 1 && dimensions[0] == 1;}
6+
size_t detail::MultiDimensionalArrayBase::numEntries() const { return std::accumulate(dimensions.begin(), dimensions.end(), size_t(1), std::multiplies<size_t>());}
7+
bool detail::MultiDimensionalArrayBase::isValid() const {return dimensions.size() > 0;}
8+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef COVER_DATACLIENT_MULTIDIMENSIONALARRAY_H
2+
#define COVER_DATACLIENT_MULTIDIMENSIONALARRAY_H
3+
4+
#include "export.h"
5+
#include <numeric>
6+
#include <cstring>
7+
#include <vector>
8+
#include <array>
9+
10+
namespace opencover{namespace dataclient{
11+
12+
namespace detail{
13+
class DATACLIENTEXPORT MultiDimensionalArrayBase{
14+
public:
15+
virtual ~MultiDimensionalArrayBase() = default;
16+
bool isScalar() const;
17+
size_t numEntries() const;
18+
bool isValid() const;
19+
20+
std::vector<size_t> dimensions;
21+
double timestamp = 0;
22+
23+
};
24+
}
25+
26+
template<typename T>
27+
struct MultiDimensionalArray : public detail::MultiDimensionalArrayBase
28+
{
29+
std::vector<T> data;
30+
};
31+
32+
33+
}}
34+
35+
#endif // COVER_DATACLIENT_MULTIDIMENSIONALARRAY_H

src/OpenCOVER/OpcUaClient/observerHandle.cpp renamed to src/OpenCOVER/DataClient/ObserverHandle.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
#include "observerHandle.h"
2-
#include "opcuaClient.h"
3-
using namespace opencover::opcua;
1+
#include "ObserverHandle.h"
2+
#include "DataClient.h"
3+
4+
using namespace opencover::dataclient;
45

56
ObserverHandle::ObserverHandle(size_t id, Client *client) : m_deleter(std::make_shared<Deleter>()){
67
m_deleter->m_id = id;
Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
#ifndef COVER_OPCUA_REGISTER_ID_H
2-
#define COVER_OPCUA_REGISTER_ID_H
1+
#ifndef COVER_DATACLIENT_OBSERVERHANDLE_H
2+
#define COVER_DATACLIENT_OBSERVERHANDLE_H
33

4+
#include "export.h"
5+
6+
#include <algorithm>
7+
#include <deque>
8+
#include <map>
49
#include <memory>
10+
#include <set>
11+
#include <string>
12+
#include <vector>
513

6-
namespace opencover{namespace opcua{
14+
namespace opencover{namespace dataclient{
715

816
class Client;
9-
class ClientNode;
17+
1018

1119
//automativally unobserves the node on deletion
12-
class ObserverHandle{
20+
class DATACLIENTEXPORT ObserverHandle{
1321
public:
1422
friend class Client;
1523
ObserverHandle() = default;
@@ -24,9 +32,9 @@ class ObserverHandle{
2432
Client *m_client = nullptr;
2533
};
2634
std::shared_ptr<Deleter> m_deleter;
27-
opencover::opcua::ClientNode *m_node = nullptr;
35+
// ClientNode *m_node = nullptr;
2836
};
2937

3038
}}
3139

32-
#endif // COVER_OPCUA_REGISTER_ID_H
40+
#endif // COVER_DATACLIENT_OBSERVERHANDLE_H

src/OpenCOVER/DataClient/export.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef COVER_DATACLIENT_EXPORT_H
2+
#define COVER_DATACLIENT_EXPORT_H
3+
4+
#include <util/coExport.h>
5+
6+
#if defined(coDataClient_EXPORTS)
7+
#define DATACLIENTEXPORT COEXPORT
8+
#else
9+
#define DATACLIENTEXPORT COIMPORT
10+
#endif
11+
12+
#endif // COVER_DATACLIENT_EXPORT_H

0 commit comments

Comments
 (0)