diff --git a/include/D_textUnifier.h b/include/D_textUnifier.h new file mode 100644 index 0000000000000000000000000000000000000000..4fff778cd963f8d3e52a4d96566ef45818424d94 --- /dev/null +++ b/include/D_textUnifier.h @@ -0,0 +1,21 @@ +#ifndef D_TEXTUNIFIER_H +#define D_TEXTUNIFIER_H + +#include <d_fct.h> + +/** A compatibility class that adds the constructor which would create a history, + * and the set_and_archive function to the D_text interface. As this does not + * have history it just calls the non-history equivalent. + * This class was introduces to avoid template specialisations in DoocsProcessScalar. + * (Local specialisations of functions don't work because one would have to + */ +struct D_textUnifier: public D_text { + + using D_text::D_text; + D_textUnifier(EqFct* eqFct, std::string doocsPropertyName); + + void set_and_archive(const std::string &str); + D_hist * get_histPointer (); +}; + +#endif // D_TEXTUNIFIER_H diff --git a/include/DoocsProcessScalar.h b/include/DoocsProcessScalar.h index 9000e29f9b0c523d0276eb539f860d369e6de471..9780d565839468355ca7392c606cfde99a90e004 100644 --- a/include/DoocsProcessScalar.h +++ b/include/DoocsProcessScalar.h @@ -130,87 +130,6 @@ namespace ChimeraTK { bool _publishZMQ{false}; }; - /** Template specialisation for D_text, which has a different interface */ - template<typename T> - class DoocsProcessScalar<T, D_text> : public D_text, public boost::noncopyable { - public: - void updateDoocsBuffer() { - // Note: we already own the location lock by specification of the - // DoocsUpdater - auto data = _processScalar->accessData(0); - this->set_value(data); - if(_publishZMQ) { - dmsg_info info; - memset(&info, 0, sizeof(info)); - auto sinceEpoch = _processScalar->getVersionNumber().getTime().time_since_epoch(); - auto time = std::chrono::duration_cast<std::chrono::microseconds>(sinceEpoch); - info.sec = time.count() / 1000000; - info.usec = time.count() % 1000000; - info.ident = _macroPulseNumberSource->accessData(0); - this->send(&info); - } - } - - DoocsProcessScalar(EqFct* eqFct, std::string doocsPropertyName, - boost::shared_ptr<typename ChimeraTK::NDRegisterAccessor<T>> const& processScalar, DoocsUpdater& updater) - : D_text(doocsPropertyName.c_str(), eqFct), _processScalar(processScalar) { - if(processScalar->isReadable()) { - updater.addVariable(ChimeraTK::ScalarRegisterAccessor<T>(processScalar), eqFct, - std::bind(&DoocsProcessScalar<T, D_text>::updateDoocsBuffer, this)); - } - } - - DoocsProcessScalar(std::string doocsPropertyName, EqFct* eqFct, - boost::shared_ptr<typename ChimeraTK::NDRegisterAccessor<T>> const& processScalar, DoocsUpdater& updater) - : D_text(doocsPropertyName.c_str(), eqFct), _processScalar(processScalar) { - if(processScalar->isReadable()) { - updater.addVariable(ChimeraTK::ScalarRegisterAccessor<T>(processScalar), eqFct, - std::bind(&DoocsProcessScalar<T, D_text>::updateDoocsBuffer, this)); - } - } - - /** - * Override the Doocs set method which is triggered by the RPC calls. - */ - void set(EqAdr* adr, EqData* data1, EqData* data2, EqFct* eqfct) override { - // only assign the value if the variable is writeable - // Otherwise the content displayed by Doocs and the value in the application - // are inconsistent - if(_processScalar->isWriteable()) { - D_text::set(adr, data1, data2, eqfct); - // let the DOOCS_T set function do all the dirty work and use the - // get_value function afterwards to get the already assigned value - _processScalar->accessData(0) = this->value(); - _processScalar->write(); - } - } - - /** - * Override the Doocs auto_init() method, which is called after initialising - * the value of the property from the config file. - */ - void auto_init(void) override { - D_text::auto_init(); - // send the current value to the device - if(_processScalar->isWriteable()) { - _processScalar->accessData(0) = D_text::value(); - _processScalar->write(); - } - } - - void publishZeroMQ() { _publishZMQ = true; } - - void setMacroPulseNumberSource(boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> macroPulseNumberSource) { - _macroPulseNumberSource = macroPulseNumberSource; - } - - protected: - boost::shared_ptr<ChimeraTK::NDRegisterAccessor<T>> _processScalar; - boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> _macroPulseNumberSource; - DataConsistencyGroup _consistencyGroup; - bool _publishZMQ{false}; - }; - } // namespace ChimeraTK #endif // __DOOCS_PROCESS_SCALAR_H__ diff --git a/src/D_textUnifier.cpp b/src/D_textUnifier.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4eeb337be906d081d3a72101edc7aa194b716d0e --- /dev/null +++ b/src/D_textUnifier.cpp @@ -0,0 +1,14 @@ +#include "D_textUnifier.h" + +// just call the constructor without history (the only one) +D_textUnifier::D_textUnifier(EqFct* eqFct, std::string doocsPropertyName) + : D_text(doocsPropertyName, eqFct){ +} + +void D_textUnifier::set_and_archive(const std::string &str){ + set_value(str); +} + +D_hist * D_textUnifier::get_histPointer(){ + return nullptr; +} diff --git a/src/DoocsPVFactory.cc b/src/DoocsPVFactory.cc index 7b39bd555be21b200652ba0cbc4a7b3633581b15..cb109276e1da496cd356154e0ef2d78232c8cfb5 100644 --- a/src/DoocsPVFactory.cc +++ b/src/DoocsPVFactory.cc @@ -4,6 +4,7 @@ #include "DoocsProcessScalar.h" #include "DoocsSpectrum.h" #include "DoocsXY.h" +#include "D_textUnifier.h" #include <d_fct.h> #include "DoocsPVFactory.h" @@ -88,7 +89,7 @@ namespace ChimeraTK { } template<> - boost::shared_ptr<D_fct> DoocsPVFactory::createDoocsScalar<std::string, D_text>( + boost::shared_ptr<D_fct> DoocsPVFactory::createDoocsScalar<std::string, D_textUnifier>( AutoPropertyDescription const& propertyDescription, DecoratorType /*decoratorType*/) { auto processVariable = _controlSystemPVManager->getProcessVariable(propertyDescription.source); @@ -106,7 +107,7 @@ namespace ChimeraTK { assert(processArray->getNumberOfChannels() == 1); assert(processArray->getNumberOfSamples() == 1); // array of strings is not supported boost::shared_ptr<D_fct> doocsPV( - new DoocsProcessScalar<std::string, D_text>(_eqFct, propertyDescription.name.c_str(), processArray, _updater)); + new DoocsProcessScalar<std::string, D_textUnifier>(_eqFct, propertyDescription.name.c_str(), processArray, _updater)); // set read only mode if configures in the xml file or for output variables if(!processArray->isWriteable() || !propertyDescription.isWriteable) { @@ -115,7 +116,7 @@ namespace ChimeraTK { // publish via ZeroMQ if configured in the xml file if(propertyDescription.publishZMQ) { - boost::dynamic_pointer_cast<DoocsProcessScalar<std::string, D_text>>(doocsPV)->publishZeroMQ(); + boost::dynamic_pointer_cast<DoocsProcessScalar<std::string, D_textUnifier>>(doocsPV)->publishZeroMQ(); } // set macro pulse number source, if configured @@ -132,7 +133,7 @@ namespace ChimeraTK { throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() + "' is used as a macro pulse number source, but it is not readable."); } - boost::dynamic_pointer_cast<DoocsProcessScalar<std::string, D_text>>(doocsPV)->setMacroPulseNumberSource( + boost::dynamic_pointer_cast<DoocsProcessScalar<std::string, D_textUnifier>>(doocsPV)->setMacroPulseNumberSource( mpnDecorated); _updater.addVariable(ChimeraTK::ScalarRegisterAccessor<int64_t>(mpnDecorated), _eqFct, [] {}); } @@ -356,7 +357,7 @@ boost::shared_ptr<D_fct> DoocsPVFactory::autoCreate(std::shared_ptr<PropertyDesc valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion); case AutoPropertyDescription::DataType::Auto: if(valueType == typeid(std::string)) { - return typedCreateScalarOrArray<D_text, std::string, std::nullptr_t, std::nullptr_t>( + return typedCreateScalarOrArray<D_textUnifier, std::string, std::nullptr_t, std::nullptr_t>( valueType, *processVariable, *autoPropertyDescription, DecoratorType::range_checking); } throw std::logic_error("DoocsPVFactory does not implement a data type it should!");