| /******************************************************************************* | |
| * Copyright (c) 2012 -2014 AIT, fortiss GmbH | |
| * All rights reserved. This program and the accompanying materials | |
| * are made available under the terms of the Eclipse Public License v1.0 | |
| * which accompanies this distribution, and is available at | |
| * http://www.eclipse.org/legal/epl-v10.html | |
| * | |
| * Contributors: | |
| * Filip Andren, Alois Zoitl - initial API and implementation and/or initial documentation | |
| *******************************************************************************/ | |
| #include "opcconnection.h" | |
| #include "opcconnectionimpl.h" | |
| #include "opceventhandler.h" | |
| #include "opcprocessvar.h" | |
| #include "Cmd_AddConnection.h" | |
| #include "Cmd_AddOPCProcessVar.h" | |
| #include "Cmd_SetProcessVarValue.h" | |
| using namespace forte::com_infra; | |
| COpcConnection::COpcConnection(const char *pa_acHost, const char *pa_acServerName, COpcEventHandler* pa_eventHandler) : | |
| m_nGroupCount(0), m_eConnectionEvent(e_Disconnected), m_acHost(pa_acHost), m_acServerName(pa_acServerName), m_acGroupName(0), m_nReqUpdateRate(0), m_nRealUpdateRate(0), m_nDeadBand(0), m_bIsConnected(false), m_bBlockingConnect(false), | |
| m_eventHandler(pa_eventHandler){ | |
| m_pOpcConnectionImpl = new COpcConnectionImpl(pa_acHost, pa_acServerName, this); | |
| } | |
| COpcConnection::~COpcConnection(){ | |
| delete m_pOpcConnectionImpl; | |
| } | |
| void COpcConnection::addGroup(const char* pa_acGroupName, unsigned long pa_nReqUpdateRate, float pa_nDeadBand, CComLayer* pa_pComCallback){ | |
| m_oSync.lock(); | |
| m_lOpcGroupMapList.pushBack(new SOpcGroupMap(pa_acGroupName, m_eventHandler->addComCallback(pa_pComCallback))); | |
| m_oSync.unlock(); | |
| m_pOpcConnectionImpl->addGroup(pa_acGroupName, pa_nReqUpdateRate, pa_nDeadBand); | |
| m_nGroupCount++; | |
| } | |
| void COpcConnection::removeGroup(const char* pa_acGroupName){ | |
| m_oSync.lock(); | |
| TOpcGroupMapList::Iterator itDelete = m_lOpcGroupMapList.begin(); | |
| TOpcGroupMapList::Iterator it_group = m_lOpcGroupMapList.begin(); | |
| TOpcGroupMapList::Iterator itEnd_group = m_lOpcGroupMapList.end(); | |
| if(it_group != itEnd_group){ | |
| if(strcmp(it_group->m_acGroupName, pa_acGroupName) == 0){ | |
| m_lOpcGroupMapList.popFront(); | |
| m_nGroupCount--; | |
| m_oSync.unlock(); | |
| return; | |
| } | |
| ++it_group; | |
| while(it_group != itEnd_group){ | |
| if(strcmp(it_group->m_acGroupName, pa_acGroupName) == 0){ | |
| m_lOpcGroupMapList.eraseAfter(itDelete); | |
| m_nGroupCount--; | |
| m_oSync.unlock(); | |
| return; | |
| } | |
| ++itDelete; | |
| ++it_group; | |
| } | |
| } | |
| m_oSync.unlock(); | |
| } | |
| int COpcConnection::send_connect(){ | |
| switch (m_eConnectionEvent){ | |
| case e_Disconnected: | |
| m_eConnectionEvent = e_Connecting; | |
| m_eventHandler->sendCommand(new CCmd_AddConnection(m_pOpcConnectionImpl)); | |
| return 0; | |
| case e_Connecting: | |
| return 0; | |
| default: // all other connection states | |
| return 1; | |
| } | |
| } | |
| int COpcConnection::send_connect(bool pa_bBlocking){ | |
| m_bBlockingConnect = pa_bBlocking; | |
| if(pa_bBlocking && !m_bIsConnected){ | |
| m_pOpcConnectionImpl->connect(); | |
| return 1; | |
| } | |
| return send_connect(); | |
| } | |
| int COpcConnection::send_addItem(COpcProcessVar* pa_pNewItem){ | |
| m_oSync.lock(); | |
| TOpcGroupMapList::Iterator itEnd_group = m_lOpcGroupMapList.end(); | |
| for(TOpcGroupMapList::Iterator it_group = m_lOpcGroupMapList.begin(); it_group != itEnd_group; ++it_group){ | |
| if(strcmp(it_group->m_acGroupName, pa_pNewItem->getItemGroupName()) == 0){ | |
| if(pa_pNewItem->getItemFunction() == COpcProcessVar::e_FBOutput){ | |
| //check if item already added | |
| TItemDataList::Iterator itEnd_item = (*it_group)->m_lReadItemsList.end(); | |
| for(TItemDataList::Iterator it_item = (*it_group)->m_lReadItemsList.begin(); it_item != itEnd_item; ++it_item){ | |
| if(strcmp(it_item->m_acItemName, pa_pNewItem->getItemName()) == 0){ | |
| m_oSync.unlock(); | |
| return 1; | |
| } | |
| } | |
| it_group->m_lReadItemsList.pushBack(new SOpcItemData(pa_pNewItem->getItemName())); | |
| break; | |
| } | |
| else if(pa_pNewItem->getItemFunction() == COpcProcessVar::e_FBInput){ | |
| //check if item already added | |
| TItemDataList::Iterator itEnd_item = (*it_group)->m_lWriteItemsList.end(); | |
| for(TItemDataList::Iterator it_item = (*it_group)->m_lWriteItemsList.begin(); it_item != itEnd_item; ++it_item){ | |
| if(strcmp(it_item->m_acItemName, pa_pNewItem->getItemName()) == 0){ | |
| m_oSync.unlock(); | |
| return 1; | |
| } | |
| } | |
| it_group->m_lWriteItemsList.pushBack(new SOpcItemData(pa_pNewItem->getItemName())); | |
| break; | |
| } | |
| } | |
| } | |
| m_oSync.unlock(); | |
| if(m_eConnectionEvent == e_Connected){ | |
| m_eventHandler->sendCommand(new CCmd_AddOPCProcessVar(m_pOpcConnectionImpl, pa_pNewItem)); | |
| return 0; | |
| } | |
| return -1; | |
| } | |
| int COpcConnection::send_sendItemData(COpcProcessVar* pa_pItem){ | |
| if (pa_pItem->getIsActive()) | |
| m_eventHandler->sendCommand(new CCmd_SetProcessVarValue(pa_pItem)); | |
| return 0; | |
| } | |
| void COpcConnection::response_connect(bool pa_bConnectionState){ | |
| m_bIsConnected = pa_bConnectionState; | |
| if(pa_bConnectionState) | |
| m_eConnectionEvent = e_Connected; | |
| else | |
| m_eConnectionEvent = e_ConnectionFailed; | |
| //m_eConnectionEvent = e_Disconnected; | |
| if(!m_bBlockingConnect){ | |
| m_oSync.lock(); | |
| TOpcGroupMapList::Iterator itEnd = m_lOpcGroupMapList.end(); | |
| for(TOpcGroupMapList::Iterator it = m_lOpcGroupMapList.begin(); it != itEnd; ++it){ | |
| m_eventHandler->executeComCallback((*it)->m_nCallbackDesc); | |
| } | |
| m_oSync.unlock(); | |
| } | |
| } | |
| void COpcConnection::response_dataReceived(const char *pa_acGroupName, TItemDataList & pa_lItemDataList){ | |
| // Loop through OpcGroups | |
| m_oSync.lock(); | |
| TOpcGroupMapList::Iterator itEnd_group = m_lOpcGroupMapList.end(); | |
| for(TOpcGroupMapList::Iterator it_group = m_lOpcGroupMapList.begin(); it_group != itEnd_group; ++it_group){ | |
| if(strcmp(it_group->m_acGroupName, pa_acGroupName) == 0){ | |
| // Loop through OpcItems in OpcGroup | |
| TItemDataList::Iterator itEnd_item = (*it_group)->m_lReadItemsList.end(); | |
| for(TItemDataList::Iterator it_item = (*it_group)->m_lReadItemsList.begin(); it_item != itEnd_item; ++it_item){ | |
| // Loop through OpcItems in ItemDataList | |
| TItemDataList::Iterator itEnd_newItem = pa_lItemDataList.end(); | |
| TItemDataList::Iterator itErase = pa_lItemDataList.begin(); | |
| for(TItemDataList::Iterator it_newItem = pa_lItemDataList.begin(); it_newItem != itEnd_newItem; ++it_newItem){ | |
| if(strcmp(it_newItem->m_acItemName, it_item->m_acItemName) == 0){ | |
| it_item->m_oItemData = it_newItem->m_oItemData; | |
| if(it_newItem == pa_lItemDataList.begin()) | |
| pa_lItemDataList.popFront(); | |
| else | |
| pa_lItemDataList.eraseAfter(itErase); | |
| break; | |
| } | |
| if(it_newItem != pa_lItemDataList.begin()) | |
| ++itErase; | |
| } | |
| if(pa_lItemDataList.isEmpty()) | |
| break; | |
| } | |
| // Change state | |
| m_eConnectionEvent = e_DataReceived; | |
| // Notify Com Layer | |
| m_eventHandler->executeComCallback(it_group->m_nCallbackDesc); | |
| break; | |
| } | |
| } | |
| m_oSync.unlock(); | |
| } | |
| void COpcConnection::response_itemAdded(COpcProcessVar* pa_pOpcItem){ | |
| // Loop through OpcGroups | |
| m_oSync.lock(); | |
| TOpcGroupMapList::Iterator itEnd_group = m_lOpcGroupMapList.end(); | |
| for(TOpcGroupMapList::Iterator it_group = m_lOpcGroupMapList.begin(); it_group != itEnd_group; ++it_group){ | |
| if(strcmp(it_group->m_acGroupName, pa_pOpcItem->getItemGroupName()) == 0){ | |
| // Change state | |
| if (pa_pOpcItem->getIsActive()) | |
| m_eConnectionEvent = e_ItemAddedOk; | |
| else | |
| m_eConnectionEvent = e_ItemAddedFailed; | |
| // Notify Com Layer | |
| m_eventHandler->executeComCallback(it_group->m_nCallbackDesc); | |
| break; | |
| } | |
| } | |
| m_oSync.unlock(); | |
| } | |
| int COpcConnection::receiveData(const char* pa_acGroupName, TOpcProcessVarList * pa_lOpcProcessVarList){ | |
| int nrData = 0; | |
| // TODO Case when lists do not match in size | |
| m_oSync.lock(); | |
| TOpcGroupMapList::Iterator itEnd_group = m_lOpcGroupMapList.end(); | |
| for(TOpcGroupMapList::Iterator it_group = m_lOpcGroupMapList.begin(); it_group != itEnd_group; ++it_group){ | |
| if(strcmp(it_group->m_acGroupName, pa_acGroupName) == 0){ | |
| TItemDataList::Iterator itEnd_item = it_group->m_lReadItemsList.end(); | |
| TItemDataList::Iterator it_item = it_group->m_lReadItemsList.begin(); | |
| TOpcProcessVarList::Iterator itEnd_procVar = pa_lOpcProcessVarList->end(); | |
| TOpcProcessVarList::Iterator it_procVar = pa_lOpcProcessVarList->begin(); | |
| while(it_procVar != itEnd_procVar && it_item != itEnd_item){ | |
| it_procVar->setNewValue(it_item->m_oItemData); | |
| nrData++; | |
| ++it_procVar; | |
| ++it_item; | |
| } | |
| break; | |
| } | |
| } | |
| m_oSync.unlock(); | |
| return nrData; | |
| } | |