blob: 32d636aed5a37a5240368c1d05d29f8fa0908fa8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 -2014 AIT, fortiss GmbH
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* 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;
}