diff --git a/include/DoocsProcessArray.h b/include/DoocsProcessArray.h index ab8fedfde2fe1450815cccec5e42d306589f4d3a..16448aa165ae0a0a0aeb0955a21e81967cd4e8e2 100644 --- a/include/DoocsProcessArray.h +++ b/include/DoocsProcessArray.h @@ -84,13 +84,13 @@ namespace ChimeraTK { void publishZeroMQ() { publishZMQ = true; } - void setMacroPulseNumberSource(boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int>> macroPulseNumberSource) { + void setMacroPulseNumberSource(boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> macroPulseNumberSource) { _macroPulseNumberSource = macroPulseNumberSource; } protected: boost::shared_ptr<ChimeraTK::NDRegisterAccessor<DOOCS_PRIMITIVE_T>> _processArray; - boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int>> _macroPulseNumberSource; + boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> _macroPulseNumberSource; bool publishZMQ{false}; // Internal function which copies the content from the DOOCS container into the diff --git a/include/DoocsProcessScalar.h b/include/DoocsProcessScalar.h index 7eeb906d4741e86113b189f3ec8b0a7f26a686a6..52565dd5e6894e06f0abefced6f04fa5a6066413 100644 --- a/include/DoocsProcessScalar.h +++ b/include/DoocsProcessScalar.h @@ -89,13 +89,13 @@ namespace ChimeraTK { void publishZeroMQ() { publishZMQ = true; } - void setMacroPulseNumberSource(boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int>> macroPulseNumberSource) { + 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<int>> _macroPulseNumberSource; + boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> _macroPulseNumberSource; bool publishZMQ{false}; }; diff --git a/include/DoocsSpectrum.h b/include/DoocsSpectrum.h index a9bdbe722b6f18547ac19e65ec288f3492be7232..a7c8328c55ec08f3b3526e6cb14a9de60caeb3c2 100644 --- a/include/DoocsSpectrum.h +++ b/include/DoocsSpectrum.h @@ -45,7 +45,7 @@ namespace ChimeraTK { void publishZeroMQ() { publishZMQ = true; } - void setMacroPulseNumberSource(boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int>> macroPulseNumberSource) { + void setMacroPulseNumberSource(boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> macroPulseNumberSource) { _macroPulseNumberSource = macroPulseNumberSource; } @@ -53,7 +53,7 @@ namespace ChimeraTK { boost::shared_ptr<ChimeraTK::NDRegisterAccessor<float>> _processArray; boost::shared_ptr<ChimeraTK::NDRegisterAccessor<float>> _startAccessor; boost::shared_ptr<ChimeraTK::NDRegisterAccessor<float>> _incrementAccessor; - boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int>> _macroPulseNumberSource; + boost::shared_ptr<ChimeraTK::NDRegisterAccessor<int64_t>> _macroPulseNumberSource; bool publishZMQ{false}; // Internal function which copies the content from the DOOCS container into the diff --git a/src/DoocsPVFactory.cc b/src/DoocsPVFactory.cc index 51ab96c7f2891bada15e21641ddfcbdc04a0f051..5d05ae66c88f2747a967a9b6188ec28f6f76eb82 100644 --- a/src/DoocsPVFactory.cc +++ b/src/DoocsPVFactory.cc @@ -63,18 +63,20 @@ namespace ChimeraTK { // set macro pulse number source, if configured if(propertyDescription.macroPulseNumberSource.size() > 0) { - auto mpnSource = _controlSystemPVManager->getProcessArray<int>(propertyDescription.macroPulseNumberSource); - if(mpnSource->getNumberOfSamples() != 1) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + auto mpnSource = _controlSystemPVManager->getProcessVariable(propertyDescription.macroPulseNumberSource); + auto mpnDecorated = getDecorator<int64_t>(mpnSource, DecoratorType::C_style_conversion); + if(mpnDecorated->getNumberOfSamples() != 1) { + throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() + "' is used as a macro pulse number source, but it has an array length of " + - std::to_string(mpnSource->getNumberOfSamples()) + ". Length must be exactly 1"); + std::to_string(mpnDecorated->getNumberOfSamples()) + ". Length must be exactly 1"); } - if(!mpnSource->isReadable()) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + if(!mpnDecorated->isReadable()) { + 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<DOOCS_PRIMITIVE_T, DOOCS_T>>(doocsPV)->setMacroPulseNumberSource( - mpnSource); + mpnDecorated); + _updater.addVariable(ChimeraTK::ScalarRegisterAccessor<int64_t>(mpnDecorated), _eqFct, [] {}); } return doocsPV; @@ -111,18 +113,20 @@ namespace ChimeraTK { // set macro pulse number source, if configured if(propertyDescription.macroPulseNumberSource.size() > 0) { - auto mpnSource = _controlSystemPVManager->getProcessArray<int>(propertyDescription.macroPulseNumberSource); - if(mpnSource->getNumberOfSamples() != 1) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + auto mpnSource = _controlSystemPVManager->getProcessVariable(propertyDescription.macroPulseNumberSource); + auto mpnDecorated = getDecorator<int64_t>(mpnSource, DecoratorType::C_style_conversion); + if(mpnDecorated->getNumberOfSamples() != 1) { + throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() + "' is used as a macro pulse number source, but it has an array length of " + - std::to_string(mpnSource->getNumberOfSamples()) + ". Length must be exactly 1"); + std::to_string(mpnDecorated->getNumberOfSamples()) + ". Length must be exactly 1"); } - if(!mpnSource->isReadable()) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + if(!mpnDecorated->isReadable()) { + 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_string>>(doocsPV)->setMacroPulseNumberSource( - mpnSource); + mpnDecorated); + _updater.addVariable(ChimeraTK::ScalarRegisterAccessor<int64_t>(mpnDecorated), _eqFct, [] {}); } return doocsPV; @@ -171,17 +175,18 @@ namespace ChimeraTK { // set macro pulse number source, if configured if(spectrumDescription.macroPulseNumberSource.size() > 0) { - auto mpnSource = _controlSystemPVManager->getProcessArray<int>(spectrumDescription.macroPulseNumberSource); - if(mpnSource->getNumberOfSamples() != 1) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + auto mpnSource = _controlSystemPVManager->getProcessVariable(spectrumDescription.macroPulseNumberSource); + auto mpnDecorated = getDecorator<int64_t>(mpnSource, DecoratorType::C_style_conversion); + if(mpnDecorated->getNumberOfSamples() != 1) { + throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() + "' is used as a macro pulse number source, but it has an array length of " + - std::to_string(mpnSource->getNumberOfSamples()) + ". Length must be exactly 1"); + std::to_string(mpnDecorated->getNumberOfSamples()) + ". Length must be exactly 1"); } - if(!mpnSource->isReadable()) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + if(!mpnDecorated->isReadable()) { + 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<DoocsSpectrum>(doocsPV)->setMacroPulseNumberSource(mpnSource); + boost::dynamic_pointer_cast<DoocsSpectrum>(doocsPV)->setMacroPulseNumberSource(mpnDecorated); } return doocsPV; @@ -296,18 +301,20 @@ namespace ChimeraTK { // set macro pulse number source, if configured if(arrayDescription.macroPulseNumberSource.size() > 0) { - auto mpnSource = _controlSystemPVManager->getProcessArray<int>(arrayDescription.macroPulseNumberSource); - if(mpnSource->getNumberOfSamples() != 1) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + auto mpnSource = _controlSystemPVManager->getProcessVariable(arrayDescription.macroPulseNumberSource); + auto mpnDecorated = getDecorator<int64_t>(mpnSource, DecoratorType::C_style_conversion); + if(mpnDecorated->getNumberOfSamples() != 1) { + throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() + "' is used as a macro pulse number source, but it has an array length of " + - std::to_string(mpnSource->getNumberOfSamples()) + ". Length must be exactly 1"); + std::to_string(mpnDecorated->getNumberOfSamples()) + ". Length must be exactly 1"); } - if(!mpnSource->isReadable()) { - throw ChimeraTK::logic_error("The property '" + mpnSource->getName() + + if(!mpnDecorated->isReadable()) { + 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<DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>>(doocsPV)->setMacroPulseNumberSource( - mpnSource); + mpnDecorated); + _updater.addVariable(ChimeraTK::ScalarRegisterAccessor<int64_t>(mpnDecorated), _eqFct, [] {}); } return doocsPV; diff --git a/tests/serverTestZeroMQ-DoocsVariableConfig.xml b/tests/serverTestZeroMQ-DoocsVariableConfig.xml index f3c014a537ad1c918eabc5516418ac6dddddd5f0..f36fbf5f8dd3eb43356ed66dfdf823e6675f1c1e 100644 --- a/tests/serverTestZeroMQ-DoocsVariableConfig.xml +++ b/tests/serverTestZeroMQ-DoocsVariableConfig.xml @@ -1,5 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <device_server xmlns="https://github.com/ChimeraTK/ControlSystemAdapter-DoocsAdapter"> + <!-- We use a type which is processed by the ReferenceTestApplication before the data properties used by the test. + Otherwise the macro pulse number gets attachted to the next value. The order is determined by the order of types + in the HolderMap, as this map is iterated. --> <macro_pulse_number_source>/INT/FROM_DEVICE_SCALAR</macro_pulse_number_source> <location name="UINT"> @@ -21,6 +24,8 @@ <import>/FLOAT</import> </location> - <import>/</import> + <location name="INT"> + <property source="/INT/TO_DEVICE_SCALAR" name="TO_DEVICE_SCALAR"/> + </location> </device_server> diff --git a/tests/src/serverTestZeroMQ.cpp b/tests/src/serverTestZeroMQ.cpp index 67491b3f83e0e2c5bdb23b5fb41f15f883ea352f..bde474be0fec55167e1d1f0fb9cf3bf73120bdbb 100644 --- a/tests/src/serverTestZeroMQ.cpp +++ b/tests/src/serverTestZeroMQ.cpp @@ -68,12 +68,16 @@ BOOST_AUTO_TEST_CASE(testScalar) { auto appPVmanager = referenceTestApplication.getPVManager(); - uint32_t expectedValue = 42; - DoocsServerTestHelper::doocsSet<uint32_t>("//UINT/TO_DEVICE_SCALAR", expectedValue); + /// Note: The data is processed by the ReferenceTestApplication in the order of the types as listed in the HolderMap + /// of the ReferenceTestApplication. INT comes before UINT and FLOAT, so the macro pulse number is first written and + /// then our values. int macroPulseNumber = 12345; DoocsServerTestHelper::doocsSet<int>("//INT/TO_DEVICE_SCALAR", macroPulseNumber); + uint32_t expectedValue = 42; + DoocsServerTestHelper::doocsSet<uint32_t>("//UINT/TO_DEVICE_SCALAR", expectedValue); + EqData dst; EqAdr ea; ea.adr("doocs://localhost:" + DoocsLauncher::rpc_no + "/F/D/UINT/FROM_DEVICE_SCALAR"); @@ -124,10 +128,10 @@ BOOST_AUTO_TEST_CASE(testScalar) { BOOST_CHECK_EQUAL(receivedInfo.sec, secs); BOOST_CHECK_EQUAL(receivedInfo.usec, usecs); BOOST_CHECK_EQUAL(receivedInfo.ident, macroPulseNumber); - expectedValue = 100 + i; - DoocsServerTestHelper::doocsSet<uint32_t>("//UINT/TO_DEVICE_SCALAR", expectedValue); ++macroPulseNumber; DoocsServerTestHelper::doocsSet<int>("//INT/TO_DEVICE_SCALAR", macroPulseNumber); + expectedValue = 100 + i; + DoocsServerTestHelper::doocsSet<uint32_t>("//UINT/TO_DEVICE_SCALAR", expectedValue); } } @@ -142,12 +146,12 @@ BOOST_AUTO_TEST_CASE(testArray) { auto appPVmanager = referenceTestApplication.getPVManager(); - std::vector<int32_t> expectedArrayValue = {42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; - DoocsServerTestHelper::doocsSet<int32_t>("//UINT/TO_DEVICE_ARRAY", expectedArrayValue); - int macroPulseNumber = 99999; DoocsServerTestHelper::doocsSet<int>("//INT/TO_DEVICE_SCALAR", macroPulseNumber); + std::vector<int32_t> expectedArrayValue = {42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; + DoocsServerTestHelper::doocsSet<int32_t>("//UINT/TO_DEVICE_ARRAY", expectedArrayValue); + EqData dst; EqAdr ea; ea.adr("doocs://localhost:" + DoocsLauncher::rpc_no + "/F/D/UINT/FROM_DEVICE_ARRAY"); @@ -200,10 +204,10 @@ BOOST_AUTO_TEST_CASE(testArray) { BOOST_CHECK_EQUAL(receivedInfo.sec, secs); BOOST_CHECK_EQUAL(receivedInfo.usec, usecs); BOOST_CHECK_EQUAL(receivedInfo.ident, macroPulseNumber); - expectedArrayValue[1] = 100 + i; - DoocsServerTestHelper::doocsSet<int32_t>("//UINT/TO_DEVICE_ARRAY", expectedArrayValue); --macroPulseNumber; DoocsServerTestHelper::doocsSet<int>("//INT/TO_DEVICE_SCALAR", macroPulseNumber); + expectedArrayValue[1] = 100 + i; + DoocsServerTestHelper::doocsSet<int32_t>("//UINT/TO_DEVICE_ARRAY", expectedArrayValue); } } @@ -218,12 +222,12 @@ BOOST_AUTO_TEST_CASE(testSpectrum) { auto appPVmanager = referenceTestApplication.getPVManager(); - std::vector<float> expectedFloatArrayValue = {42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; - DoocsServerTestHelper::doocsSet<float>("//FLOAT/TO_DEVICE_ARRAY", expectedFloatArrayValue); - int macroPulseNumber = -100; DoocsServerTestHelper::doocsSet<int>("//INT/TO_DEVICE_SCALAR", macroPulseNumber); + std::vector<float> expectedFloatArrayValue = {42, 43, 44, 45, 46, 47, 48, 49, 50, 51}; + DoocsServerTestHelper::doocsSet<float>("//FLOAT/TO_DEVICE_ARRAY", expectedFloatArrayValue); + EqData dst; EqAdr ea; ea.adr("doocs://localhost:" + DoocsLauncher::rpc_no + "/F/D/FLOAT/FROM_DEVICE_ARRAY"); @@ -277,10 +281,10 @@ BOOST_AUTO_TEST_CASE(testSpectrum) { BOOST_CHECK_EQUAL(receivedInfo.sec, secs); BOOST_CHECK_EQUAL(receivedInfo.usec, usecs); BOOST_CHECK_EQUAL(receivedInfo.ident, macroPulseNumber); - expectedFloatArrayValue[1] = 100 + i; - DoocsServerTestHelper::doocsSet<float>("//FLOAT/TO_DEVICE_ARRAY", expectedFloatArrayValue); macroPulseNumber *= -2; DoocsServerTestHelper::doocsSet<int>("//INT/TO_DEVICE_SCALAR", macroPulseNumber); + expectedFloatArrayValue[1] = 100 + i; + DoocsServerTestHelper::doocsSet<float>("//FLOAT/TO_DEVICE_ARRAY", expectedFloatArrayValue); } }