/* * VirtualInstrument.cc * * Created on: Jan 17, 2013 * Author: f.casimir */ #include // std::find #include "DicError.hh" #include "TimeUtil.hh" #include "DDServerInterfaceConfig.hh" #include "VirtualInstrument.hh" #include "VirtualInstrumentInterval.hh" using namespace AMDA::Parameters; namespace AMDA { namespace DDServerInterface { VirtualInstrument::VirtualInstrument(VirtualInstrumentManager& pVirtualInstrumentManager, const std::string& viName) : _virtualInstrumentManager(pVirtualInstrumentManager), _viName(viName), _id(-1) { // Set user host _ddClient.setUserHost(_virtualInstrumentManager.getUserHost()); /// Open Connection _id = _ddClient.DD_SetVariable(const_cast(_viName.c_str())); LOG4CXX_INFO(gLogger,"ParamGetDDBase: DD_SetVariable("<< _viName << ") returns = (" << _id << ")"); if (_id < 0) { _ddClient.DD_Close(99); BOOST_THROW_EXCEPTION(exception() << errno_code(_id)); } /// Set GlobalStart { _globalStartTime = getDDTimeInfo("GlobalStart"); } /// Set GlobalStop { _globalStopTime = getDDTimeInfo("GlobalStop"); } /// Set MinSampling { const InfoList& lInfoList = getDDInfo("MinSampling"); _minSampling = lInfoList.begin()->second->at(0); } /// Set MaxSampling { const InfoList& lInfoList = getDDInfo("MaxSampling"); if (lInfoList.empty()) { //Sampling constant _maxSampling = _minSampling; } else { _maxSampling = lInfoList.begin()->second->at(0); } } /// Set FillValue { const InfoList& lInfoList = getDDInfo("FillValue"); if ( ! lInfoList.empty()) { _fillValue = (*lInfoList.begin()->second)[0]; } else { _fillValue = NAN; } } } VirtualInstrument::~VirtualInstrument() { if(_id!=-1) { _ddClient.DD_Close(_id); } VirtualInstrumentManager::releaseInstance(); } double VirtualInstrument::getDDTimeInfo(const char *timeTag) { DD_data_t *data; _ddClient.DD_GetInform(_id, const_cast(timeTag), &data); if (data->type != DD_CHAR || data->DimNumber != 1 || data->Dimensions[0] <= 0) { LOG4CXX_ERROR(gLogger, "DD_GetInform(" << timeTag << ") not good type "); BOOST_THROW_EXCEPTION(exception() << errno_code(AMDA_ERROR_UNKNOWN)); } LOG4CXX_DEBUG(gLogger, "getDDTimeInfo(" << timeTag << ") = " << (char*)data->Variables[0]); return TimeUtil::readTimeInIso((char *) data->Variables[0]); } template void VirtualInstrument::setInfoValues( InfoList& storage, const std::string& pInfoName, unsigned int pNbData, void* data) { // Read data type* lFloatData = reinterpret_cast(data); InfoValuesSPtr lInfo = InfoValuesSPtr(new InfoValues(pNbData)); lInfo->assign(lFloatData,lFloatData+pNbData); storage.insert(std::pair( pInfoName, lInfo)); } unsigned int getNbTab( unsigned int pNbDimension, unsigned int pDepth, int* pDimensions) { if ( pDepth == pNbDimension) { return 1; } else { return pDimensions[pDepth]*getNbTab(pNbDimension,pDepth+1,pDimensions); } } template void VirtualInstrument::recurseInfoValues( InfoList& storage, const std::string& pInfoName, unsigned int pNbDimension, int* pDimensions, void* data) { if ( pNbDimension == 1 ) { setInfoValues(storage,pInfoName,pDimensions[0],data); } else { int lTabSize = pDimensions[pNbDimension-1]; unsigned int lStepIndex = getNbTab(pNbDimension-1,0,pDimensions); for ( unsigned int i = 0; i < lStepIndex; ++i) { unsigned int lStepPointer = sizeof(Type)*i*lTabSize; std::stringstream lInfoName; lInfoName << pInfoName << "_" << i; setInfoValues(storage,lInfoName.str(), lTabSize, (char *)data + lStepPointer); } } } const InfoList& VirtualInstrument::getDDInfo(const char* pIinfoName) { DD_data_t *data = NULL; auto lIt = _infoMap.find(pIinfoName); if (lIt == _infoMap.end()) { int result = 0; InfoList& infoList = _infoMap[pIinfoName]; if ((result = _ddClient.DD_GetInform( _id, const_cast(pIinfoName), &data)) >= 0) { LOG4CXX_DEBUG(gLogger,"ParamGetDDBase:getInfoDD( "<< _id << ", " << pIinfoName << ") returns = ( return: " << result << ", type: " << data->type << ", DimNumber: " << data->DimNumber << ", Dimensions[0]: " << data->Dimensions[0] << ", VarNumber: " << data->VarNumber << ")"); if (data->VarNumber == 1) { if (data->type == DD_FLOAT) { recurseInfoValues(infoList, pIinfoName, data->DimNumber, data->Dimensions, *data->Variables); } else if (data->type == DD_DOUBLE) { recurseInfoValues(infoList, pIinfoName, data->DimNumber, data->Dimensions, *data->Variables); } else if (data->type == DD_SHORT) { recurseInfoValues(infoList, pIinfoName, data->DimNumber, data->Dimensions, *data->Variables); } } else { } } else { LOG4CXX_INFO(gLogger, "ParamGetDDBase:getInfoDD( "<< _id << ", " << pIinfoName << ") returns = (" << result << ")"); } return infoList; } return lIt->second; } AMDA::Parameters::ContainerType VirtualInstrument::getParamContainerType(DD_data_t *data) { if (data == NULL) return AMDA::Parameters::ContainerType::CT_UNKNOWN; switch (data->DimNumber) { case 1 : //vector or scalar if (data->Dimensions[0] > 1) return AMDA::Parameters::ContainerType::CT_TAB1D; else if (data->Dimensions[0] == 1) return AMDA::Parameters::ContainerType::CT_SCALAR; break; case 2 : if (data->Dimensions[1] == 1) { if (data->Dimensions[0] == 1) return AMDA::Parameters::ContainerType::CT_SCALAR; else if (data->Dimensions[0] > 1) return AMDA::Parameters::ContainerType::CT_TAB1D; } else if (data->Dimensions[1] > 1) { if (data->Dimensions[0] == 1) return AMDA::Parameters::ContainerType::CT_TAB1D; else if (data->Dimensions[0] > 1) return AMDA::Parameters::ContainerType::CT_TAB2D; } break; default: return AMDA::Parameters::ContainerType::CT_UNKNOWN; } return AMDA::Parameters::ContainerType::CT_UNKNOWN; } //TODO Replace by DD_Client::getParamType AMDA::Parameters::Base::Pusher* VirtualInstrument::getParamPusher( const std::string& pParName) { AMDA::Parameters::Base::Pusher* lPusher = nullptr; int error = 0; DD_Client lDDClient; lDDClient.setUserHost(_virtualInstrumentManager.getUserHost()); DD_data_t *data = nullptr; LOG4CXX_DEBUG(gLogger, "VirtualInstrument::getParamPusher: DD_SetVariable("<< _viName << ") call"); int lId = lDDClient.DD_SetVariable(const_cast(_viName.c_str())); LOG4CXX_INFO(gLogger, "VirtualInstrument::getParamPusher: DD_SetVariable("<< _viName << ") returns = (" << _id << ")"); if (lId < 0) { lDDClient.DD_Close(99); BOOST_THROW_EXCEPTION(exception() << errno_code(lId)); } char startTime[TIMELENGTH]; Double2DD_Time(startTime,_globalStartTime); LOG4CXX_DEBUG(gLogger, "VirtualInstrument::getParamPusher: DD_SetTime("<< startTime << ") call"); if ((error = lDDClient.DD_SetTime(lId, startTime)) < 0) { lDDClient.DD_Close(lId); LOG4CXX_ERROR(gLogger, "VirtualInstrument::getParamPusher: DD_SetTime("<< startTime << ") returns = (" << error << ")"); BOOST_THROW_EXCEPTION(exception() << errno_code(error)); } LOG4CXX_INFO(gLogger, "VirtualInstrument::getParamPusher: DD_SetTime("<< startTime << ") returns = (" << error << ")"); char timeInt[TIMELENGTH]; Double2DD_Time(timeInt, _maxSampling); LOG4CXX_DEBUG(gLogger, "VirtualInstrument::getParamPusher: DD_GetData("<< pParName << "," << timeInt << ") call"); error = lDDClient.DD_GetData(lId, const_cast(pParName.c_str()), timeInt, &data); while (error == MOREDELAY) { sleep(2); error = lDDClient.DD_GetData(lId, const_cast(pParName.c_str()), timeInt, &data); } lDDClient.DD_Close(lId); if (error >= 0 || error == MOREDATA) { //#define DD_SHORT 4 //#define DD_INT 1 //#define DD_FLOAT 2 //#define DD_DOUBLE 3 //#define DD_CHAR 0 LOG4CXX_DEBUG(gLogger, "getParamPusher data->type = " << data->type << ", dimNumber :" << data->DimNumber <<" var number : " << data->VarNumber); const int numDataType = data->type; AMDA::Parameters::ContainerType containerType = getParamContainerType(data); switch (containerType) { case AMDA::Parameters::ContainerType::CT_SCALAR : switch (numDataType) { case DD_FLOAT: lPusher = new Pusher(); break; case DD_INT : lPusher = new Pusher(); break; case DD_SHORT : lPusher = new Pusher(); break; default : BOOST_THROW_EXCEPTION( exception() << errno_code(AMDA_TYPE_DATA_UNKNOWN)); } break; case AMDA::Parameters::ContainerType::CT_TAB1D : switch (numDataType) { case DD_FLOAT: lPusher = new Pusher(data->Dimensions[0]); break; case DD_INT : lPusher = new Pusher(data->Dimensions[0]); break; case DD_SHORT : lPusher = new Pusher(data->Dimensions[0]); break; default : BOOST_THROW_EXCEPTION( exception() << errno_code(AMDA_TYPE_DATA_UNKNOWN)); } break; case AMDA::Parameters::ContainerType::CT_TAB2D : switch (numDataType) { case DD_FLOAT: lPusher = new Pusher(data->Dimensions[0],data->Dimensions[1]); break; case DD_INT : lPusher = new Pusher(data->Dimensions[0],data->Dimensions[1]); break; case DD_SHORT : lPusher = new Pusher(data->Dimensions[0],data->Dimensions[1]); break; default : BOOST_THROW_EXCEPTION( exception() << errno_code(AMDA_TYPE_DATA_UNKNOWN)); } break; default: LOG4CXX_INFO(gLogger, "VirtualInstrument::getParamPusher( "<< lId <<", " << pParName << ") - Unknown container type"); lDDClient.DD_Close(lId); BOOST_THROW_EXCEPTION(exception() << errno_code(AMDA_TYPE_DATA_UNKNOWN)); } lPusher->setFillValue(_fillValue); } else { LOG4CXX_INFO(gLogger, "VirtualInstrument::getParamPusher( "<< lId <<", " << pParName << ") returns = (" << error << ")"); lDDClient.DD_Close(lId); BOOST_THROW_EXCEPTION(exception() << errno_code(error)); } return lPusher; } VI::ParamFlowSPtr VirtualInstrument::getParamFlow(const std::string& pParamName, TimeIntervalListSPtr pTimeIntervalList) { // Define function to compare two TimeIntervalListSptr. // This used to identify if the requested TimeIntervalList already exist in _intervalList attribute or not. auto lIt = std::find_if( _intervalList.begin(), _intervalList.end(), [&](const IntervalList::value_type& val) -> bool { if (val.first->size() != pTimeIntervalList->size()) { return false; } else { TimeIntervalList::const_iterator itA = val.first->begin(); TimeIntervalList::const_iterator itB = pTimeIntervalList->begin(); while (itA != val.first->end()) { if ( (itA->_startTime != itB->_startTime) || (itA->_stopTime != itB->_stopTime) ) { return false; } else { ++itA; ++itB; } } return true; } }); // TimeIntervalListSPtr not found if (lIt == _intervalList.end()) { std::pair value(pTimeIntervalList, VirtualIntrumentIntervalSPtr(new VirtualInstrumentInterval(*this, pTimeIntervalList.get()))); std::pair lIter = _intervalList.insert(value); lIt = lIter.first; } else { // Nothing to do. } return lIt->second->getParamFlow(pParamName); } } /* namespace DDServerInterface */ } /* namespace AMDA */