ChimeraTK-ApplicationCore 04.06.00
Loading...
Searching...
No Matches
DeviceModule.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#include "DeviceModule.h"
4
5#include "Application.h"
6#include "DeviceManager.h"
7#include "ModuleGroup.h"
8#include "Utilities.h"
9
10#include <ChimeraTK/DeviceBackend.h>
11#include <ChimeraTK/Utilities.h>
12
13namespace ChimeraTK {
14
15 /********************************************************************************************************************/
16
17 DeviceModule::DeviceModule(ModuleGroup* owner, const std::string& deviceAliasOrCDD, const std::string& triggerPath,
18 std::function<void(ChimeraTK::Device&)> initialisationHandler, const std::string& pathInDevice)
19 : ModuleGroup(owner, "**DeviceModule**") {
20 // get/create the DeviceManager and add the initialisation handler
21 auto dm = Application::getInstance().getDeviceManager(deviceAliasOrCDD);
22 _dm = dm;
23
24 _pathInDevice = pathInDevice;
25
26 if(initialisationHandler) {
27 addInitialisationHandler(std::move(initialisationHandler));
28 }
29
30 // check and store the trigger path
31 if(!triggerPath.empty() && triggerPath[0] != '/') {
32 throw ChimeraTK::logic_error("DeviceModule triggerPath must be absolute!");
33 }
34 _triggerPath = triggerPath;
35
36 // create the process variables in the model from the device registers
37 // -------------------------------------------------------------------
38 _model = owner->getModel().add(*this);
39 auto neighbourDirectory = _model.visit(
40 Model::returnDirectory, Model::getNeighbourDirectory, Model::returnFirstHit(Model::DirectoryProxy{}));
41 assert(neighbourDirectory.isValid());
42
43 // get the virtualised version of the device for the given pathInDevice
44 auto nodeList = dm->getNodesList();
45
46 // iterate all registers and add them to the model
47 for(auto& node : nodeList) {
48 // skip registers which are in a different directory than specified by pathInDevice
49 if(!boost::starts_with(node.getRegisterName(), _pathInDevice)) {
50 continue;
51 }
52
53 // obtain register name relative to pathInDevice
54 assert(boost::starts_with(node.getRegisterName(), _pathInDevice));
55 auto cut = pathInDevice.size();
56 if(!boost::ends_with(pathInDevice, "/")) {
57 ++cut;
58 }
59 auto relativePath = node.getRegisterName().substr(cut);
60
62 auto dir = neighbourDirectory.addDirectoryRecursive(Utilities::getPathName(relativePath));
63
64 // add the PV to the directory (or get it if already existing)
65 auto var = dir.addVariable(Utilities::getUnqualifiedName(relativePath));
66 node.setOwningModule(this);
67
68 // connect the node and the PV
69 _model.addVariable(var, node);
70 }
71 }
72
73 /********************************************************************************************************************/
74
76 // First clean up the model before moving the module itself.
77 if(other._model.isValid()) {
78 Model::DirectoryProxy neighbourDirectory;
79 try {
80 neighbourDirectory = other._model.visit(
81 Model::returnDirectory, Model::getNeighbourDirectory, Model::returnFirstHit(Model::DirectoryProxy{}));
82 assert(neighbourDirectory.isValid());
83
84 auto dm = _dm.lock();
85 if(dm) {
86 for(const auto& reg : dm->getDevice().getRegisterCatalogue()) {
87 if(reg.getNumberOfDimensions() > 1) {
88 continue;
89 }
90 std::string registerName = reg.getRegisterName();
91 if(!boost::starts_with(registerName, _pathInDevice)) {
92 continue;
93 }
94
95 // find the right PV in the model
96 VariableNetworkNode theNode;
98 neighbourDirectory.visitByPath(registerName, [&](auto proxy) {
99 if constexpr(isVariable(proxy)) {
100 assert(proxy.isValid());
101
102 // find the right node (belonging to our device) to remove
103 for(auto& proxyNode : proxy.getNodes()) {
104 if(proxyNode->getType() == NodeType::Device && proxyNode->getDeviceAlias() == getDeviceAliasOrURI()) {
105 theProxy = proxy;
106 theNode = *proxyNode;
107 break;
108 }
109 }
110 }
111 });
112 if(theNode.isValid()) {
113 assert(theProxy.isValid());
114 theProxy.removeNode(theNode);
115 }
116 }
117 }
118 }
119 catch(ChimeraTK::logic_error& e) {
120 std::cerr << e.what() << std::endl;
121 std::exit(1);
122 }
123 }
124
125 _model = std::move(other._model);
126 other._model = {};
127 if(_model.isValid()) {
128 _model.informMove(*this);
129 }
130 ModuleGroup::operator=(std::move(other));
131 return *this;
132 }
133
134 /********************************************************************************************************************/
135
137 return *_dm.lock();
138 }
139
140 /********************************************************************************************************************/
141
143 return *_dm.lock();
144 }
145
146 /********************************************************************************************************************/
147
151
152 /********************************************************************************************************************/
153
154 const std::string& DeviceModule::getDeviceAliasOrURI() const {
155 return _dm.lock()->getDeviceAliasOrURI();
156 }
157
158 /********************************************************************************************************************/
159
160 void DeviceModule::addInitialisationHandler(std::function<void(ChimeraTK::Device&)> initialisationHandler) {
161 _dm.lock()->addInitialisationHandler(std::move(initialisationHandler));
162 }
163
164 /********************************************************************************************************************/
165
166 void DeviceModule::reportException(std::string errMsg) {
167 _dm.lock()->reportException(std::move(errMsg));
168 }
169
170 /********************************************************************************************************************/
171
172 SetDMapFilePath::SetDMapFilePath(const std::string& dmapFilePath) {
173 ChimeraTK::setDMapFilePath(dmapFilePath);
174 }
175
176 /********************************************************************************************************************/
177
178} // namespace ChimeraTK
boost::shared_ptr< DeviceManager > getDeviceManager(const std::string &aliasOrCDD)
Return the DeviceManager for the given alias name or CDD.
static Application & getInstance()
Obtain instance of the application.
Implements access to a ChimeraTK::Device.
DeviceModule & operator=(DeviceModule &&other) noexcept
Move assignment.
boost::weak_ptr< DeviceManager > _dm
The corresponding DeviceManager.
void addInitialisationHandler(std::function< void(ChimeraTK::Device &)> initialisationHandler)
void reportException(std::string errMsg)
Use this function to report an exception.
DeviceManager & getDeviceManager()
Return the corresponding DeviceManager.
const std::string & getDeviceAliasOrURI() const
Model::DeviceModuleProxy getModel()
Model::DeviceModuleProxy _model
void addVariable(ProcessVariableProxy &variable, VariableNetworkNode &node)
Definition Model.cc:352
bool visitByPath(std::string_view path, VISITOR visitor) const
Resolve the given path and call the visitor for the found object.
Definition Model.h:1906
ModuleGroupProxy add(ModuleGroup &module)
Definition Model.cc:164
void removeNode(const VariableNetworkNode &node)
Remove VariableNetworkNode from the list of nodes. Note: Will invalidate return value of getNodes()!
Definition Model.cc:403
bool isValid() const
Check if the model is valid.
Definition Model.cc:31
auto visit(VISITOR visitor, Args... args) const
Traverse the model using the specified filter and call the visitor functor for each ModuleGroup,...
Definition Model.h:1451
ModuleGroup & operator=(ModuleGroup &&other) noexcept
Move assignment.
friend class DeviceModule
Definition ModuleGroup.h:48
ChimeraTK::Model::ModuleGroupProxy getModel()
Return the application model proxy representing this module.
Definition ModuleGroup.h:40
SetDMapFilePath(const std::string &dmapFilePath)
Class describing a node of a variable network.
constexpr ReturnFirstHitWithValue< void > returnFirstHit()
Stop the search after the first hit and return.
Definition Model.h:790
std::string getPathName(const std::string &qualifiedName)
Return all but the last components of the given qualified name.
Definition Utilities.cc:29
std::string getUnqualifiedName(const std::string &qualifiedName)
Return the last component of the given qualified path name.
Definition Utilities.cc:19
InvalidityTracer application module.