-
Notifications
You must be signed in to change notification settings - Fork 9
/
DashboardClient.hpp
139 lines (113 loc) · 5.72 KB
/
DashboardClient.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019-2021 (c) Christian von Arnim, ISW University of Stuttgart (for umati and VDW e.V.)
* Copyright 2020 (c) Dominik Basner, Sotec GmbH (for VDW e.V.)
* Copyright 2021 (c) Moritz Walker, ISW University of Stuttgart (for umati and VDW e.V.)
* Copyright 2021 (c) Marius Dege, basysKom GmbH
*/
#pragma once
#include "IDashboardDataClient.hpp"
#include "OpcUaTypeReader.hpp"
#include "IPublisher.hpp"
#include <ModelOpcUa/ModelInstance.hpp>
#include <map>
#include <set>
#include <mutex>
namespace Umati {
namespace Dashboard {
/**
* DashboardClient
* Depends on instances of:
* - IDashboardDataClient (like Umati::OpcUa::OpcUaClient)
* - IPublisher (like Umati::MqttPublisher::MqttPublisher)
*
* How DashboardClient works
* - While the IDashboardDataClient instance acts as a source and IPublisher as the sink.
* - DashboardClient is initialized by DashboardMachineObserver when a machine was found.
* - DashboardMachineObserver calls addDataSet to integrate the machine into the
* system. Besides, DashboardMachineObserver forwards the Publish() function to the
* DashboardOpcUaClient which contains a thread calling the fowarded Publish() method
* every second. DashboardClient itself then resolves topics and payloads and forwards this
* to the IPublisher.
* All further functions are protected and used internally
*/
class DashboardClient {
public:
DashboardClient(std::shared_ptr<IDashboardDataClient> pDashboardDataClient,
std::shared_ptr<IPublisher> pPublisher,
std::shared_ptr<OpcUaTypeReader> pTypeReader);
void addDataSet(
const ModelOpcUa::NodeId_t &startNodeId,
const std::shared_ptr<ModelOpcUa::StructureNode> &pTypeDefinition,
const std::string &channel,
const std::string &onlineChannel);
void Publish();
void Unsubscribe(ModelOpcUa::NodeId_t nodeId);
protected:
struct LastMessage_t {
std::string payload;
time_t lastSent;
};
struct DataSetStorage_t {
ModelOpcUa::NodeId_t startNodeId;
std::string channel;
std::string onlineChannel;
std::shared_ptr<const ModelOpcUa::SimpleNode> node;
std::mutex values_mutex;
std::map<std::shared_ptr<const ModelOpcUa::Node>, nlohmann::json> values;
};
static std::string getJson(const std::shared_ptr<DataSetStorage_t> &pDataSetStorage);
std::shared_ptr<const ModelOpcUa::SimpleNode> TransformToNodeIds(
ModelOpcUa::NodeId_t startNode,
const std::shared_ptr<ModelOpcUa::StructureNode> &pTypeDefinition
);
std::shared_ptr<const ModelOpcUa::PlaceholderNode> BrowsePlaceholder(
ModelOpcUa::NodeId_t startNode,
std::shared_ptr<const ModelOpcUa::StructurePlaceholderNode> pStructurePlaceholder);
void subscribeValues(
const std::shared_ptr<const ModelOpcUa::SimpleNode> pNode,
std::map<std::shared_ptr<const ModelOpcUa::Node>, nlohmann::json> &valueMap,
std::mutex &valueMap_mutex
);
std::vector<std::shared_ptr<Dashboard::IDashboardDataClient::ValueSubscriptionHandle>> m_subscribedValues;
std::shared_ptr<IDashboardDataClient> m_pDashboardDataClient;
std::shared_ptr<IPublisher> m_pPublisher;
std::shared_ptr<OpcUaTypeReader> m_pTypeReader;
std::set<ModelOpcUa::NodeId_t> browsedNodes;
std::recursive_mutex m_dataSetMutex;
std::list<std::shared_ptr<DataSetStorage_t>> m_dataSets;
std::map<std::string, LastMessage_t> m_latestMessages;
bool isMandatoryOrOptionalVariable(const std::shared_ptr<const ModelOpcUa::SimpleNode> &pNode);
void handleSubscribeChildNodes(const std::shared_ptr<const ModelOpcUa::SimpleNode> &pNode,
std::map<std::shared_ptr<const ModelOpcUa::Node>, nlohmann::json> &valueMap,
std::mutex &valueMap_mutex);
void handleSubscribePlaceholderChildNode(const std::shared_ptr<const ModelOpcUa::Node> &pChildNode,
std::map<std::shared_ptr<const ModelOpcUa::Node>, nlohmann::json> &valueMap,
std::mutex &valueMap_mutex);
void subscribeValue(const std::shared_ptr<const ModelOpcUa::SimpleNode> &pNode,
std::map<std::shared_ptr<const ModelOpcUa::Node>, nlohmann::json> &valueMap,
std::mutex &valueMap_mutex);
void handleSubscribeChildNode(const std::shared_ptr<const ModelOpcUa::Node> &pChildNode,
std::map<std::shared_ptr<const ModelOpcUa::Node>, nlohmann::json> &valueMap,
std::mutex &valueMap_mutex);
void preparePlaceholderNodesTypeId(
const std::shared_ptr<const ModelOpcUa::StructurePlaceholderNode> &pStructurePlaceholder,
std::shared_ptr<ModelOpcUa::PlaceholderNode> &pPlaceholderNode,
std::list<ModelOpcUa::BrowseResult_t> &browseResults);
std::shared_ptr<DataSetStorage_t> prepareDataSetStorage(const ModelOpcUa::NodeId_t &startNodeId,
const std::shared_ptr<ModelOpcUa::StructureNode> &pTypeDefinition,
const std::string &channel,
const std::string &onlineChannel);
bool OptionalAndMandatoryTransformToNodeId(const ModelOpcUa::NodeId_t &startNode,
std::list<std::shared_ptr<const ModelOpcUa::Node>> &foundChildNodes,
const std::shared_ptr<ModelOpcUa::StructureNode> &pChild);
bool OptionalAndMandatoryPlaceholderTransformToNodeId(const ModelOpcUa::NodeId_t &startNode,
std::list<std::shared_ptr<const ModelOpcUa::Node>> &foundChildNodes,
const std::shared_ptr<ModelOpcUa::StructureNode> &pChild);
void TransformToNodeIdNodeNotFoundLog(const ModelOpcUa::NodeId_t &startNode,
const std::shared_ptr<ModelOpcUa::StructureNode> &pChild) const;
};
}
}