ChimeraTK-DeviceAccess-TangoBackend 00.01.02
Loading...
Searching...
No Matches
TangoBackend.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
4#include "TangoBackend.h"
5
6#include "OfflineCache.h"
7#include "RegisterCatalogue.h"
9
10#include <ChimeraTK/BackendFactory.h>
11#include <ChimeraTK/Exception.h>
12#include <ChimeraTK/MetadataCatalogue.h>
13#include <ChimeraTK/RegisterCatalogue.h>
14
15#include <tango/tango.h>
16
17#include <boost/shared_ptr.hpp>
18
19#include <utility>
20
21static struct BackendRegisterer {
22 BackendRegisterer() {
23 std::cout << "TangoBackend::BackendRegisterer: registering backend type tango" << std::endl;
24 ChimeraTK::BackendFactory::getInstance().registerBackendType("tango", &ChimeraTK::TangoBackend::createInstance);
25 }
26} backendRegisterer;
27
28/**********************************************************************************************************************/
29/**********************************************************************************************************************/
30/**********************************************************************************************************************/
31
32namespace ChimeraTK {
33 // This is from public API, cannot change currently
34 // NOLINTNEXTLINE(performance-unnecessary-value-param)
35 boost::shared_ptr<DeviceBackend> TangoBackend::createInstance(
36 std::string address, [[maybe_unused]] std::map<std::string, std::string> parameters) {
37 // This is from public API, cannot change currently
38 // NOLINTNEXTLINE(performance-unnecessary-value-param)
39 std::optional<std::string> cacheFile;
40 auto it = parameters.find("cacheFile");
41 if(it != parameters.end()) {
42 cacheFile = it->second;
43 }
44
45 return boost::shared_ptr<DeviceBackend>(new TangoBackend(std::move(address), cacheFile));
46 }
47
48 /********************************************************************************************************************/
49
50 TangoBackend::TangoBackend(std::string address, std::optional<std::string> cacheFile)
51 : DeviceBackendImpl(), _address(std::move(address)) {
52 auto it = _address.find("%23");
53 if(it != std::string::npos) {
54 _address.replace(it, 3, "#");
55 }
56 if(cacheFile) {
57 _registerCatalogue = OfflineCache(cacheFile.value()).read();
58 }
59 FILL_VIRTUAL_FUNCTION_TEMPLATE_VTABLE(getRegisterAccessor_impl);
60 }
61
62 /********************************************************************************************************************/
63
65 // Apparently there is no way to reconnect the proxy via public api. All the relevant connection API
66 // is protected.
67 if(_deviceProxy) {
68 _deviceProxy.reset();
69 }
70
71 try {
72 _deviceProxy = std::make_shared<Tango::DeviceProxy>(_address);
73 _deviceProxy->set_transparency_reconnection(false);
74 auto catalogue = TangoRegisterCatalogue();
75
76 // https://github.com/tango-controls/pytango/issues/375
77 // Some interaction with the server is needed. DeviceProxy will not throw in its constructor
78 std::unique_ptr<Tango::AttributeInfoListEx> attributes(_deviceProxy->attribute_list_query_ex());
79 for(auto& attr : *attributes) {
80 catalogue.addRegister(TangoRegisterInfo(attr));
81 }
82 _registerCatalogue = std::move(catalogue);
83 }
84 catch(Tango::WrongNameSyntax& ex) {
85 throw ChimeraTK::logic_error(
86 "Invalid Tango device address " + _address + ", " + static_cast<std::string>(ex.errors[0].desc));
87 }
88 catch(Tango::ConnectionFailed& ex) {
89 std::string message = "Cannot connect to " + _address + ", " + static_cast<std::string>(ex.errors[0].desc);
90 setException(message);
91 throw ChimeraTK::runtime_error(message);
92 }
93 catch(CORBA::Exception& ex) {
94 std::string message = "Cannot connect to " + _address + "for unknown reason";
95 setException(message);
96 throw ChimeraTK::runtime_error(message);
97 }
98
99 setOpenedAndClearException();
100 }
101
102 /********************************************************************************************************************/
103
105 _opened = false;
106 _deviceProxy.reset();
107 }
108
109 /********************************************************************************************************************/
110
111 template<typename UserType>
112 boost::shared_ptr<NDRegisterAccessor<UserType>> TangoBackend::getRegisterAccessor_impl(
113 const RegisterPath& registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags) {
114 boost::shared_ptr<NDRegisterAccessor<UserType>> p;
115
116 auto info = _registerCatalogue.getBackendRegister(registerPathName);
117
118 auto sharedThis = boost::static_pointer_cast<TangoBackend>(shared_from_this());
119
120 switch(info.attributeInfo.data_format) {
121 case Tango::AttrDataFormat::SPECTRUM:
122 case Tango::AttrDataFormat::SCALAR: {
123 switch(info.attributeInfo.data_type) {
124 case Tango::DEV_BOOLEAN:
126 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
127 break;
128 case Tango::DEV_SHORT:
130 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
131 break;
132 case Tango::DEV_LONG:
134 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
135 break;
136 case Tango::DEV_FLOAT:
138 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
139 break;
140 case Tango::DEV_DOUBLE:
142 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
143 break;
144 case Tango::DEV_USHORT:
146 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
147 break;
148 case Tango::DEV_ULONG:
150 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
151 break;
152 case Tango::DEV_STRING:
154 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
155 break;
156 case Tango::DEV_STATE:
158 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
159 break;
160 case Tango::DEV_UCHAR:
162 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
163 break;
164 case Tango::DEV_LONG64:
166 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
167 break;
168 case Tango::DEV_ULONG64:
170 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
171 break;
172 // Compatibility for old servers that have DEV_INT
173 case 27:
175 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
176 break;
177 case Tango::DEV_ENUM:
179 sharedThis, info, registerPathName, numberOfWords, wordOffsetInRegister, flags));
180 break;
181 default:
182 throw ChimeraTK::logic_error("Unsupported Tango type " + std::to_string(info.attributeInfo.data_type));
183 break;
184 }
185 break;
186 }
187 case Tango::AttrDataFormat::IMAGE:
188 break;
189 case Tango::AttrDataFormat::FMT_UNKNOWN:
190 default:
191 throw ChimeraTK::logic_error(
192 "Broken Tango attribute database information. " + registerPathName + " does not come with a data format");
193 }
194
195 p->setExceptionBackend(sharedThis);
196 return p;
197 }
198
199 /********************************************************************************************************************/
200
201 RegisterCatalogue TangoBackend::getRegisterCatalogue() const {
202 return RegisterCatalogue(_registerCatalogue.clone());
203 }
204
205 /********************************************************************************************************************/
206
208 return std::string("Tango Device: ") + _address;
209 }
210
211 /********************************************************************************************************************/
212
213} // namespace ChimeraTK
TangoRegisterCatalogue read()
std::string readDeviceInfo() override
TangoBackend(std::string address, std::optional< std::string > cacheFile)
RegisterCatalogue getRegisterCatalogue() const override
boost::shared_ptr< NDRegisterAccessor< UserType > > getRegisterAccessor_impl(const RegisterPath &registerPathName, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
static boost::shared_ptr< DeviceBackend > createInstance(std::string address, std::map< std::string, std::string > parameters)