You need to sign in or sign up before continuing.
Commit df497744 authored by Pavel Vainerman's avatar Pavel Vainerman

(Modbus): продолжаю выносить код в базовый класс

parent a15d2cc4
...@@ -181,6 +181,7 @@ AC_CONFIG_FILES([Makefile ...@@ -181,6 +181,7 @@ AC_CONFIG_FILES([Makefile
extensions/IOControl/libUniSetIOControl.pc extensions/IOControl/libUniSetIOControl.pc
extensions/RTUExchange/Makefile extensions/RTUExchange/Makefile
extensions/RTUExchange/libUniSetRTU.pc extensions/RTUExchange/libUniSetRTU.pc
extensions/ModbusMaster/Makefile
extensions/ModbusSlave/Makefile extensions/ModbusSlave/Makefile
extensions/ModbusSlave/libUniSetMBSlave.pc extensions/ModbusSlave/libUniSetMBSlave.pc
extensions/MBTCPMaster/Makefile extensions/MBTCPMaster/Makefile
......
...@@ -8,16 +8,18 @@ libUniSetMBTCPMaster_la_LDFLAGS = -version-info $(UMBTCP_VER) ...@@ -8,16 +8,18 @@ libUniSetMBTCPMaster_la_LDFLAGS = -version-info $(UMBTCP_VER)
libUniSetMBTCPMaster_la_LIBADD = $(top_builddir)/lib/libUniSet.la \ libUniSetMBTCPMaster_la_LIBADD = $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \ $(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \ $(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(top_builddir)/extensions/ModbusMaster/libMBMaster.la \
$(SIGC_LIBS) $(SIGC_LIBS)
libUniSetMBTCPMaster_la_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) libUniSetMBTCPMaster_la_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory -I$(top_builddir)/extensions/ModbusMaster $(SIGC_CFLAGS)
libUniSetMBTCPMaster_la_SOURCES = MBTCPMaster.cc libUniSetMBTCPMaster_la_SOURCES = MBTCPMaster.cc
@PACKAGE@_mbtcpmaster_SOURCES = main.cc @PACKAGE@_mbtcpmaster_SOURCES = main.cc
@PACKAGE@_mbtcpmaster_LDADD = libUniSetMBTCPMaster.la $(top_builddir)/lib/libUniSet.la \ @PACKAGE@_mbtcpmaster_LDADD = libUniSetMBTCPMaster.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \ $(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \ $(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(top_builddir)/extensions/ModbusMaster/libMBMaster.la \
$(SIGC_LIBS) $(SIGC_LIBS)
@PACKAGE@_mbtcpmaster_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) @PACKAGE@_mbtcpmaster_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory -I$(top_builddir)/extensions/ModbusMaster $(SIGC_CFLAGS)
# install # install
devel_include_HEADERS = *.h devel_include_HEADERS = *.h
......
#!/bin/sh #!/bin/sh
./uniset-start.sh -g ./uniset-mbtcpmaster \ ./uniset-start.sh -f ./uniset-mbtcpmaster \
--confile test.xml \ --confile test.xml \
--mbtcp-name MBMaster1 \ --mbtcp-name MBMaster1 \
--smemory-id SharedMemory \ --smemory-id SharedMemory \
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <Exceptions.h> #include <Exceptions.h>
#include <UniSetTypes.h>
#include <extensions/Extensions.h> #include <extensions/Extensions.h>
#include "MBExchange.h" #include "MBExchange.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -21,7 +20,6 @@ force(false), ...@@ -21,7 +20,6 @@ force(false),
force_out(false), force_out(false),
mbregFromID(false), mbregFromID(false),
sidExchangeMode(DefaultObjectId), sidExchangeMode(DefaultObjectId),
exchangeMode(emNone),
activated(false), activated(false),
noQueryOptimization(false), noQueryOptimization(false),
no_extimer(false), no_extimer(false),
...@@ -57,19 +55,10 @@ pollActivated(false) ...@@ -57,19 +55,10 @@ pollActivated(false)
if( stat_time > 0 ) if( stat_time > 0 )
ptStatistic.setTiming(stat_time*1000); ptStatistic.setTiming(stat_time*1000);
recv_timeout = conf->getArgPInt("--" + prefix + "-recv-timeout",it.getProp("recv_timeout"), 500); // recv_timeout = conf->getArgPInt("--" + prefix + "-recv-timeout",it.getProp("recv_timeout"), 500);
//
int tout = conf->getArgPInt("--" + prefix + "-timeout",it.getProp("timeout"), 5000); // int tout = conf->getArgPInt("--" + prefix + "-timeout",it.getProp("timeout"), 5000);
// для совместимости со старым RTUExchange // ptTimeout.setTiming(tout);
// надо обратывать и all-timeout
tout = conf->getArgPInt("--" + prefix + "-all-timeout",it.getProp("all_timeout"), tout);
ptTimeout.setTiming(tout);
tout = conf->getArgPInt("--" + prefix + "-reopen-timeout",it.getProp("reopen_timeout"), 10000);
ptReopen.setTiming(tout);
aftersend_pause = conf->getArgPInt("--" + prefix + "-aftersend-pause",it.getProp("aftersend_pause"),0);
noQueryOptimization = conf->getArgInt("--" + prefix + "-no-query-optimization",it.getProp("no_query_optimization")); noQueryOptimization = conf->getArgInt("--" + prefix + "-no-query-optimization",it.getProp("no_query_optimization"));
...@@ -80,7 +69,7 @@ pollActivated(false) ...@@ -80,7 +69,7 @@ pollActivated(false)
initPause = conf->getArgPInt("--" + prefix + "-initPause",it.getProp("initPause"), 3000); initPause = conf->getArgPInt("--" + prefix + "-initPause",it.getProp("initPause"), 3000);
sleepPause_usec = conf->getArgPInt("--" + prefix + "-sleepPause-usec",it.getProp("sleepPause"), 100); sleepPause_usec = conf->getArgPInt("--" + prefix + "-sleepPause-usec",it.getProp("slepePause"), 100);
force = conf->getArgInt("--" + prefix + "-force",it.getProp("force")); force = conf->getArgInt("--" + prefix + "-force",it.getProp("force"));
force_out = conf->getArgInt("--" + prefix + "-force-out",it.getProp("force_out")); force_out = conf->getArgInt("--" + prefix + "-force-out",it.getProp("force_out"));
...@@ -99,7 +88,7 @@ pollActivated(false) ...@@ -99,7 +88,7 @@ pollActivated(false)
throw SystemError(err.str()); throw SystemError(err.str());
} }
int heartbeatTime = conf->getArgPInt("--" + prefix + "-heartbeat-time",it.getProp("heartbeatTime"),conf->getHeartBeatTime()); int heartbeatTime = getHeartBeatTime();
if( heartbeatTime ) if( heartbeatTime )
ptHeartBeat.setTiming(heartbeatTime); ptHeartBeat.setTiming(heartbeatTime);
else else
...@@ -143,9 +132,6 @@ void MBExchange::help_print( int argc, const char* const* argv ) ...@@ -143,9 +132,6 @@ void MBExchange::help_print( int argc, const char* const* argv )
cout << "--prefix-name name - ObjectId (имя) процесса. По умолчанию: MBExchange1" << endl; cout << "--prefix-name name - ObjectId (имя) процесса. По умолчанию: MBExchange1" << endl;
cout << "--prefix-confnode name - Настроечная секция в конф. файле <name>. " << endl; cout << "--prefix-confnode name - Настроечная секция в конф. файле <name>. " << endl;
cout << "--prefix-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек." << endl; cout << "--prefix-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек." << endl;
cout << "--prefix-recv-timeout msec - Таймаут на приём одного сообщения" << endl;
cout << "--prefix-timeout msec - Таймаут для определения отсутствия соединения" << endl;
cout << "--prefix-reopen-timeout msec - Таймаут для 'переоткрытия соединения' при отсутсвия соединения msec милисекунд. По умолчанию 10 сек." << endl;
cout << "--prefix-heartbeat-id name - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl; cout << "--prefix-heartbeat-id name - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl;
cout << "--prefix-heartbeat-max val - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl; cout << "--prefix-heartbeat-max val - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--prefix-ready-timeout msec - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl; cout << "--prefix-ready-timeout msec - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
...@@ -158,27 +144,10 @@ void MBExchange::help_print( int argc, const char* const* argv ) ...@@ -158,27 +144,10 @@ void MBExchange::help_print( int argc, const char* const* argv )
cout << "--prefix-filter-value val - Считывать список опрашиваемых датчиков, только у которых field=value" << endl; cout << "--prefix-filter-value val - Считывать список опрашиваемых датчиков, только у которых field=value" << endl;
cout << "--prefix-statistic-sec sec - Выводить статистику опроса каждые sec секунд" << endl; cout << "--prefix-statistic-sec sec - Выводить статистику опроса каждые sec секунд" << endl;
cout << "--prefix-sm-ready-timeout - время на ожидание старта SM" << endl; cout << "--prefix-sm-ready-timeout - время на ожидание старта SM" << endl;
cout << "--prefix-exchange-mode-id - Идентификатор (AI) датчика, позволяющего управлять работой процесса" << endl;
cout << "--prefix-set-prop-prefix val - Использовать для свойств указанный или пустой префикс." << endl;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
MBExchange::~MBExchange() MBExchange::~MBExchange()
{ {
for( RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
if( it1->second->rtu )
{
delete it1->second->rtu;
it1->second->rtu = 0;
}
RTUDevice* d(it1->second);
for( RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
delete it->second;
delete it1->second;
}
delete shm; delete shm;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -205,8 +174,6 @@ void MBExchange::step() ...@@ -205,8 +174,6 @@ void MBExchange::step()
if( !checkProcActive() ) if( !checkProcActive() )
return; return;
updateRespondSensors();
if( sidHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() ) if( sidHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
{ {
try try
...@@ -237,7 +204,7 @@ void MBExchange::setProcActive( bool st ) ...@@ -237,7 +204,7 @@ void MBExchange::setProcActive( bool st )
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MBExchange::sigterm( int signo ) void MBExchange::sigterm( int signo )
{ {
dlog[Debug::WARN] << myname << ": ********* SIGTERM(" << signo << ") ********" << endl; dlog[Debug::WARN] << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
setProcActive(false); setProcActive(false);
UniSetObject_LT::sigterm(signo); UniSetObject_LT::sigterm(signo);
} }
...@@ -277,7 +244,7 @@ bool MBExchange::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec ) ...@@ -277,7 +244,7 @@ bool MBExchange::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
MBExchange::DeviceType MBExchange::getDeviceType( const std::string& dtype ) MBExchange::DeviceType MBExchange::getDeviceType( const std::string dtype )
{ {
if( dtype.empty() ) if( dtype.empty() )
return dtUnknown; return dtUnknown;
...@@ -288,9 +255,6 @@ MBExchange::DeviceType MBExchange::getDeviceType( const std::string& dtype ) ...@@ -288,9 +255,6 @@ MBExchange::DeviceType MBExchange::getDeviceType( const std::string& dtype )
if( dtype == "rtu" || dtype == "RTU" ) if( dtype == "rtu" || dtype == "RTU" )
return dtRTU; return dtRTU;
if( dtype == "rtu188" || dtype == "RTU188" )
return dtRTU188;
return dtUnknown; return dtUnknown;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
...@@ -302,40 +266,20 @@ void MBExchange::initIterators() ...@@ -302,40 +266,20 @@ void MBExchange::initIterators()
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
shm->initDIterator(d->resp_dit); shm->initDIterator(d->resp_dit);
shm->initAIterator(d->mode_ait);
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it ) for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{ {
for( PList::iterator it2=it->second->slst.begin();it2!=it->second->slst.end(); ++it2 ) for( PList::iterator it2=it->second->slst.begin();it2!=it->second->slst.end(); ++it2 )
{ {
shm->initDIterator(it2->dit); shm->initDIterator(it2->dit);
shm->initAIterator(it2->ait); shm->initAIterator(it2->ait);
shm->initAIterator(it2->t_ait);
} }
} }
} }
for( ThresholdList::iterator t=thrlist.begin(); t!=thrlist.end(); ++t )
{
shm->initDIterator(t->dit);
shm->initAIterator(t->ait);
shm->initAIterator(t->t_ait);
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool MBExchange::checkUpdateSM( bool wrFunc, long mdev ) bool MBExchange::checkUpdateSM( bool wrFunc )
{ {
if( exchangeMode == emSkipExchange || mdev == emSkipExchange ) if( wrFunc && exchangeMode == emReadOnly )
{
if( wrFunc )
return true; // данные для посылки, должны обновляться всегда (чтобы быть актуальными)
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "(checkUpdateSM):"
<< " skip... mode='emSkipExchange' " << endl;
return false;
}
if( wrFunc && (exchangeMode == emReadOnly || mdev == emReadOnly) )
{ {
if( dlog.debugging(Debug::LEVEL3) ) if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "(checkUpdateSM):" dlog[Debug::LEVEL3] << "(checkUpdateSM):"
...@@ -343,7 +287,7 @@ bool MBExchange::checkUpdateSM( bool wrFunc, long mdev ) ...@@ -343,7 +287,7 @@ bool MBExchange::checkUpdateSM( bool wrFunc, long mdev )
return false; return false;
} }
if( !wrFunc && (exchangeMode == emWriteOnly || mdev == emWriteOnly) ) if( !wrFunc && exchangeMode == emWriteOnly )
{ {
if( dlog.debugging(Debug::LEVEL3) ) if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "(checkUpdateSM):" dlog[Debug::LEVEL3] << "(checkUpdateSM):"
...@@ -351,7 +295,7 @@ bool MBExchange::checkUpdateSM( bool wrFunc, long mdev ) ...@@ -351,7 +295,7 @@ bool MBExchange::checkUpdateSM( bool wrFunc, long mdev )
return false; return false;
} }
if( wrFunc && (exchangeMode == emSkipSaveToSM || mdev == emSkipSaveToSM) ) if( wrFunc && exchangeMode == emSkipSaveToSM )
{ {
if( dlog.debugging(Debug::LEVEL3) ) if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "(checkUpdateSM):" dlog[Debug::LEVEL3] << "(checkUpdateSM):"
...@@ -437,11 +381,6 @@ std::ostream& operator<<( std::ostream& os, MBExchange::RTUDevice& d ) ...@@ -437,11 +381,6 @@ std::ostream& operator<<( std::ostream& os, MBExchange::RTUDevice& d )
return os; return os;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBExchange::RegInfo* r )
{
return os << (*r);
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBExchange::RegInfo& r ) std::ostream& operator<<( std::ostream& os, MBExchange::RegInfo& r )
{ {
os << " id=" << r.id os << " id=" << r.id
...@@ -669,7 +608,7 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty ...@@ -669,7 +608,7 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty
if( p->nbit >= 0 ) if( p->nbit >= 0 )
{ {
bool set = b[p->nbit]; bool set = b[p->nbit];
IOBase::processingAsDI( p, set, shm, true ); IOBase::processingAsDI( p, set, shm, force );
return true; return true;
} }
...@@ -678,10 +617,10 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty ...@@ -678,10 +617,10 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty
if( p->stype == UniversalIO::DigitalInput || if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput ) p->stype == UniversalIO::DigitalOutput )
{ {
IOBase::processingAsDI( p, data[0], shm, true ); IOBase::processingAsDI( p, data[0], shm, force );
} }
else else
IOBase::processingAsAI( p, (signed short)(data[0]), shm, true ); IOBase::processingAsAI( p, (signed short)(data[0]), shm, force );
return true; return true;
} }
...@@ -696,10 +635,10 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty ...@@ -696,10 +635,10 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty
if( p->stype == UniversalIO::DigitalInput || if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput ) p->stype == UniversalIO::DigitalOutput )
{ {
IOBase::processingAsDI( p, data[0], shm, true ); IOBase::processingAsDI( p, data[0], shm, force );
} }
else else
IOBase::processingAsAI( p, (signed short)(data[0]), shm, true ); IOBase::processingAsAI( p, (signed short)(data[0]), shm, force );
return true; return true;
} }
...@@ -708,10 +647,10 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty ...@@ -708,10 +647,10 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty
if( p->stype == UniversalIO::DigitalInput || if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput ) p->stype == UniversalIO::DigitalOutput )
{ {
IOBase::processingAsDI( p, data[0], shm, true ); IOBase::processingAsDI( p, data[0], shm, force );
} }
else else
IOBase::processingAsAI( p, (unsigned short)data[0], shm, true ); IOBase::processingAsAI( p, (unsigned short)data[0], shm, force );
return true; return true;
} }
...@@ -725,43 +664,28 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty ...@@ -725,43 +664,28 @@ bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty
} }
VTypes::Byte b(data[0]); VTypes::Byte b(data[0]);
IOBase::processingAsAI( p, b.raw.b[p->nbyte-1], shm, true ); IOBase::processingAsAI( p, b.raw.b[p->nbyte-1], shm, force );
return true; return true;
} }
else if( p->vType == VTypes::vtF2 ) else if( p->vType == VTypes::vtF2 )
{ {
VTypes::F2 f(data,VTypes::F2::wsize()); VTypes::F2 f(data,VTypes::F2::wsize());
IOBase::processingFasAI( p, (float)f, shm, true ); IOBase::processingFasAI( p, (float)f, shm, force );
}
else if( p->vType == VTypes::vtF2r )
{
VTypes::F2r f(data,VTypes::F2r::wsize());
IOBase::processingFasAI( p, (float)f, shm, true );
} }
else if( p->vType == VTypes::vtF4 ) else if( p->vType == VTypes::vtF4 )
{ {
VTypes::F4 f(data,VTypes::F4::wsize()); VTypes::F4 f(data,VTypes::F4::wsize());
IOBase::processingFasAI( p, (float)f, shm, true ); IOBase::processingFasAI( p, (float)f, shm, force );
} }
else if( p->vType == VTypes::vtI2 ) else if( p->vType == VTypes::vtI2 )
{ {
VTypes::I2 i2(data,VTypes::I2::wsize()); VTypes::I2 i2(data,VTypes::I2::wsize());
IOBase::processingAsAI( p, (int)i2, shm, true ); IOBase::processingAsAI( p, (int)i2, shm, force );
}
else if( p->vType == VTypes::vtI2r )
{
VTypes::I2r i2(data,VTypes::I2::wsize());
IOBase::processingAsAI( p, (int)i2, shm, true );
} }
else if( p->vType == VTypes::vtU2 ) else if( p->vType == VTypes::vtU2 )
{ {
VTypes::U2 u2(data,VTypes::U2::wsize()); VTypes::U2 u2(data,VTypes::U2::wsize());
IOBase::processingAsAI( p, (unsigned int)u2, shm, true ); IOBase::processingAsAI( p, (unsigned int)u2, shm, force );
}
else if( p->vType == VTypes::vtU2r )
{
VTypes::U2r u2(data,VTypes::U2::wsize());
IOBase::processingAsAI( p, (unsigned int)u2, shm, true );
} }
return true; return true;
...@@ -799,15 +723,6 @@ bool MBExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it ) ...@@ -799,15 +723,6 @@ bool MBExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
{ {
RegInfo* p(it->second); RegInfo* p(it->second);
if( dev->mode == emSkipExchange )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): SKIP EXCHANGE (mode=emSkipExchange) "
<< " mbaddr=" << ModbusRTU::addr2str(dev->mbaddr)
<< endl;
return true;
}
if( dlog.debugging(Debug::LEVEL3) ) if( dlog.debugging(Debug::LEVEL3) )
{ {
dlog[Debug::LEVEL3] << myname << "(pollRTU): poll " dlog[Debug::LEVEL3] << myname << "(pollRTU): poll "
...@@ -854,7 +769,7 @@ bool MBExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it ) ...@@ -854,7 +769,7 @@ bool MBExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
case ModbusRTU::fnReadOutputRegisters: case ModbusRTU::fnReadOutputRegisters:
{ {
ModbusRTU::ReadOutputRetMessage ret = mb->read03(dev->mbaddr,p->mbreg,p->q_count); ModbusRTU::ReadOutputRetMessage ret = mb->read03(dev->mbaddr, p->mbreg,p->q_count);
for( int i=0; i<p->q_count; i++,it++ ) for( int i=0; i<p->q_count; i++,it++ )
it->second->mbval = ret.data[i]; it->second->mbval = ret.data[i];
it--; it--;
...@@ -1008,40 +923,6 @@ void MBExchange::updateSM() ...@@ -1008,40 +923,6 @@ void MBExchange::updateSM()
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
if( d->mode_id != DefaultObjectId )
{
try
{
if( !shm->isLocalwork() )
d->mode = shm->localGetValue(d->mode_ait,d->mode_id);
}
catch(IOController_i::NameNotFound &ex)
{
dlog[Debug::LEVEL3] << myname << "(updateSM):(NameNotFound) " << ex.err << endl;
}
catch(IOController_i::IOBadParam& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateSM):(IOBadParam) " << ex.err << endl;
}
catch(IONotifyController_i::BadRange )
{
dlog[Debug::LEVEL3] << myname << "(updateSM): (BadRange)..." << endl;
}
catch( Exception& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateSM): " << ex << endl;
}
catch(CORBA::SystemException& ex)
{
dlog[Debug::LEVEL3] << myname << "(updateSM): CORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch(...)
{
dlog[Debug::LEVEL3] << myname << "(updateSM): check modeSensor..catch ..." << endl;
}
}
// обновление датчиков связи происходит в другом потоке // обновление датчиков связи происходит в другом потоке
// чтобы не зависеть от TCP таймаутов // чтобы не зависеть от TCP таймаутов
// см. updateRespondSensors() // см. updateRespondSensors()
...@@ -1055,8 +936,6 @@ void MBExchange::updateSM() ...@@ -1055,8 +936,6 @@ void MBExchange::updateSM()
updateRTU(it); updateRTU(it);
else if( d->dtype == dtMTR ) else if( d->dtype == dtMTR )
updateMTR(it); updateMTR(it);
else if( d->dtype == dtRTU188 )
updateRTU188(it);
} }
catch(IOController_i::NameNotFound &ex) catch(IOController_i::NameNotFound &ex)
{ {
...@@ -1109,7 +988,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1109,7 +988,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
if( !save && write_only ) if( !save && write_only )
return; return;
if( !checkUpdateSM(save,r->dev->mode) ) if( !checkUpdateSM(save) )
return; return;
// если требуется инициализация и она ещё не произведена, // если требуется инициализация и она ещё не произведена,
...@@ -1118,7 +997,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1118,7 +997,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
return; return;
if( dlog.debugging(Debug::LEVEL3) ) if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateP): sid=" << p->si.id dlog[Debug::LEVEL3] << "updateP: sid=" << p->si.id
<< " mbval=" << r->mbval << " mbval=" << r->mbval
<< " vtype=" << p->vType << " vtype=" << p->vType
<< " rnum=" << p->rnum << " rnum=" << p->rnum
...@@ -1280,7 +1159,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1280,7 +1159,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
return; return;
} }
else if( p->vType == VTypes::vtF2 || p->vType == VTypes::vtF2r ) else if( p->vType == VTypes::vtF2 )
{ {
RegMap::iterator i(p->reg->rit); RegMap::iterator i(p->reg->rit);
if( save ) if( save )
...@@ -1288,18 +1167,9 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1288,18 +1167,9 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
if( r->mb_initOK ) if( r->mb_initOK )
{ {
float f = IOBase::processingFasAO( p, shm, force_out ); float f = IOBase::processingFasAO( p, shm, force_out );
if( p->vType == VTypes::vtF2 )
{
VTypes::F2 f2(f); VTypes::F2 f2(f);
for( int k=0; k<VTypes::F2::wsize(); k++, i++ ) for( int k=0; k<VTypes::F2::wsize(); k++, i++ )
i->second->mbval = f2.raw.v[k]; i->second->mbval = f2.raw.v[k];
}
else if( p->vType == VTypes::vtF2r )
{
VTypes::F2r f2(f);
for( int k=0; k<VTypes::F2r::wsize(); k++, i++ )
i->second->mbval = f2.raw.v[k];
}
r->sm_initOK = true; r->sm_initOK = true;
} }
...@@ -1310,21 +1180,10 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1310,21 +1180,10 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
for( int k=0; k<VTypes::F2::wsize(); k++, i++ ) for( int k=0; k<VTypes::F2::wsize(); k++, i++ )
data[k] = i->second->mbval; data[k] = i->second->mbval;
float f=0; VTypes::F2 f(data,VTypes::F2::wsize());
if( p->vType == VTypes::vtF2 )
{
VTypes::F2 f1(data,VTypes::F2::wsize());
f = (float)f1;
}
else if( p->vType == VTypes::vtF2r )
{
VTypes::F2r f1(data,VTypes::F2r::wsize());
f = (float)f1;
}
delete[] data; delete[] data;
IOBase::processingFasAI( p, f, shm, force ); IOBase::processingFasAI( p, (float)f, shm, force );
} }
} }
else if( p->vType == VTypes::vtF4 ) else if( p->vType == VTypes::vtF4 )
...@@ -1352,7 +1211,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1352,7 +1211,7 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
IOBase::processingFasAI( p, (float)f, shm, force ); IOBase::processingFasAI( p, (float)f, shm, force );
} }
} }
else if( p->vType == VTypes::vtI2 || p->vType == VTypes::vtI2r ) else if( p->vType == VTypes::vtI2 )
{ {
RegMap::iterator i(p->reg->rit); RegMap::iterator i(p->reg->rit);
if( save ) if( save )
...@@ -1360,18 +1219,10 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1360,18 +1219,10 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
if( r->mb_initOK ) if( r->mb_initOK )
{ {
long v = IOBase::processingAsAO( p, shm, force_out ); long v = IOBase::processingAsAO( p, shm, force_out );
if( p->vType == VTypes::vtI2 )
{
VTypes::I2 i2(v); VTypes::I2 i2(v);
for( int k=0; k<VTypes::I2::wsize(); k++, i++ ) for( int k=0; k<VTypes::I2::wsize(); k++, i++ )
i->second->mbval = i2.raw.v[k]; i->second->mbval = i2.raw.v[k];
}
else if( p->vType == VTypes::vtI2r )
{
VTypes::I2r i2(v);
for( int k=0; k<VTypes::I2::wsize(); k++, i++ )
i->second->mbval = i2.raw.v[k];
}
r->sm_initOK = true; r->sm_initOK = true;
} }
} }
...@@ -1381,23 +1232,13 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1381,23 +1232,13 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
for( int k=0; k<VTypes::I2::wsize(); k++, i++ ) for( int k=0; k<VTypes::I2::wsize(); k++, i++ )
data[k] = i->second->mbval; data[k] = i->second->mbval;
int v = 0;
if( p->vType == VTypes::vtI2 )
{
VTypes::I2 i2(data,VTypes::I2::wsize()); VTypes::I2 i2(data,VTypes::I2::wsize());
v = (int)i2;
}
else if( p->vType == VTypes::vtI2r )
{
VTypes::I2r i2(data,VTypes::I2::wsize());
v = (int)i2;
}
delete[] data; delete[] data;
IOBase::processingAsAI( p, v, shm, force );
IOBase::processingAsAI( p, (int)i2, shm, force );
} }
} }
else if( p->vType == VTypes::vtU2 || p->vType == VTypes::vtU2r ) else if( p->vType == VTypes::vtU2 )
{ {
RegMap::iterator i(p->reg->rit); RegMap::iterator i(p->reg->rit);
if( save ) if( save )
...@@ -1405,18 +1246,9 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1405,18 +1246,9 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
if( r->mb_initOK ) if( r->mb_initOK )
{ {
long v = IOBase::processingAsAO( p, shm, force_out ); long v = IOBase::processingAsAO( p, shm, force_out );
if( p->vType == VTypes::vtU2 )
{
VTypes::U2 u2(v); VTypes::U2 u2(v);
for( int k=0; k<VTypes::U2::wsize(); k++, i++ ) for( int k=0; k<VTypes::U2::wsize(); k++, i++ )
i->second->mbval = u2.raw.v[k]; i->second->mbval = u2.raw.v[k];
}
else if( p->vType == VTypes::vtU2r )
{
VTypes::U2r u2(v);
for( int k=0; k<VTypes::U2::wsize(); k++, i++ )
i->second->mbval = u2.raw.v[k];
}
r->sm_initOK = true; r->sm_initOK = true;
} }
...@@ -1427,26 +1259,16 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1427,26 +1259,16 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
for( int k=0; k<VTypes::U2::wsize(); k++, i++ ) for( int k=0; k<VTypes::U2::wsize(); k++, i++ )
data[k] = i->second->mbval; data[k] = i->second->mbval;
unsigned int v = 0;
if( p->vType == VTypes::vtU2 )
{
VTypes::U2 u2(data,VTypes::U2::wsize()); VTypes::U2 u2(data,VTypes::U2::wsize());
v = (unsigned int)u2;
}
else if( p->vType == VTypes::vtU2r )
{
VTypes::U2r u2(data,VTypes::U2::wsize());
v = (unsigned int)u2;
}
delete[] data; delete[] data;
IOBase::processingAsAI( p, v, shm, force );
IOBase::processingAsAI( p, (unsigned int)u2, shm, force );
} }
} }
return; return;
} }
catch(IOController_i::NameNotFound& ex) catch(IOController_i::NameNotFound &ex)
{ {
dlog[Debug::LEVEL3] << myname << "(updateRSProperty):(NameNotFound) " << ex.err << endl; dlog[Debug::LEVEL3] << myname << "(updateRSProperty):(NameNotFound) " << ex.err << endl;
} }
...@@ -1480,14 +1302,32 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1480,14 +1302,32 @@ void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
void MBExchange::updateMTR( RegMap::iterator& rit ) void MBExchange::updateMTR( RegMap::iterator& rit )
{ {
RegInfo* r(rit->second); RegInfo* r(rit->second);
if( !r || !r->dev )
return;
using namespace ModbusRTU; using namespace ModbusRTU;
bool save = isWriteFunction( r->mbfunc ); bool save = isWriteFunction( r->mbfunc );
if( !checkUpdateSM(save,r->dev->mode) ) if( save && exchangeMode == emReadOnly )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateMTR):"
<< " skip... mode=emReadOnly " << endl;
return; return;
}
if( !save && exchangeMode == emWriteOnly )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateMTR):"
<< " skip... mode=emWriteOnly " << endl;
return;
}
if( save && exchangeMode == emSkipSaveToSM )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateMTR):"
<< " skip... mode=emSkipSaveToSM " << endl;
return;
}
{ {
for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it ) for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it )
...@@ -1707,56 +1547,22 @@ void MBExchange::updateMTR( RegMap::iterator& rit ) ...@@ -1707,56 +1547,22 @@ void MBExchange::updateMTR( RegMap::iterator& rit )
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MBExchange::updateRTU188( RegMap::iterator& rit ) void MBExchange::updateRTU188( RegMap::iterator& it )
{ {
RegInfo* r(rit->second); RegInfo* r(it->second);
if( !r || !r->dev || !r->dev->rtu ) if( !r->dev->rtu )
return; return;
using namespace ModbusRTU; using namespace ModbusRTU;
bool save = isWriteFunction( r->mbfunc ); // bool save = false;
// пока-что функции записи в обмене с RTU188
// не реализованы
if( isWriteFunction(r->mbfunc) ) if( isWriteFunction(r->mbfunc) )
{ {
// save = true;
cerr << myname << "(updateRTU188): write reg(" << dat2str(r->mbreg) << ") to RTU188 NOT YET!!!" << endl; cerr << myname << "(updateRTU188): write reg(" << dat2str(r->mbreg) << ") to RTU188 NOT YET!!!" << endl;
return; return;
} }
if( exchangeMode == emSkipExchange || r->dev->mode == emSkipExchange )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateRTU188):"
<< " skip... mode=emSkipExchange " << endl;
return;
}
if( save && (exchangeMode == emReadOnly || r->dev->mode == emReadOnly) )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateRTU188):"
<< " skip... mode=emReadOnly " << endl;
return;
}
if( !save && ( exchangeMode == emWriteOnly || r->dev->mode == emWriteOnly) )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateRTU188):"
<< " skip... mode=emWriteOnly " << endl;
return;
}
if( save && ( exchangeMode == emSkipSaveToSM || r->dev->mode == emSkipSaveToSM) )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateRT188):"
<< " skip... mode=emSkipSaveToSM " << endl;
return;
}
for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it ) for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it )
{ {
try try
...@@ -1765,11 +1571,14 @@ void MBExchange::updateRTU188( RegMap::iterator& rit ) ...@@ -1765,11 +1571,14 @@ void MBExchange::updateRTU188( RegMap::iterator& rit )
{ {
bool set = r->dev->rtu->getState(r->rtuJack,r->rtuChan,it->stype); bool set = r->dev->rtu->getState(r->rtuJack,r->rtuChan,it->stype);
IOBase::processingAsDI( &(*it), set, shm, force ); IOBase::processingAsDI( &(*it), set, shm, force );
continue;
} }
else if( it->stype == UniversalIO::AnalogInput )
if( it->stype == UniversalIO::AnalogInput )
{ {
long val = r->dev->rtu->getInt(r->rtuJack,r->rtuChan,it->stype); long val = r->dev->rtu->getInt(r->rtuJack,r->rtuChan,it->stype);
IOBase::processingAsAI( &(*it), val, shm, force ); IOBase::processingAsAI( &(*it),val, shm, force );
continue;
} }
} }
catch(IOController_i::NameNotFound &ex) catch(IOController_i::NameNotFound &ex)
...@@ -1912,15 +1721,6 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it ) ...@@ -1912,15 +1721,6 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
if( !IOBase::initItem(&p,it,shm,&dlog,myname) ) if( !IOBase::initItem(&p,it,shm,&dlog,myname) )
return false; return false;
// проверяем не пороговый ли это датчик (т.е. не связанный с обменом)
// тогда заносим его в отдельный список
if( p.t_ai != DefaultObjectId )
{
thrlist.push_back(p);
return true;
}
if( it.getIntProp(prop_prefix + "rawdata") ) if( it.getIntProp(prop_prefix + "rawdata") )
{ {
p.cal.minRaw = 0; p.cal.minRaw = 0;
...@@ -2016,21 +1816,6 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD ...@@ -2016,21 +1816,6 @@ bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUD
if( !initMTRitem(it,r) ) if( !initMTRitem(it,r) )
return false; return false;
} }
else if( dev->dtype == MBExchange::dtRTU188 )
{
// only for RTU188
if( !initRTU188item(it,r) )
return false;
UniversalIO::IOTypes t = UniSetTypes::getIOType(it.getProp("iotype"));
r->mbreg = RTUStorage::getRegister(r->rtuJack,r->rtuChan,t);
r->mbfunc = RTUStorage::getFunction(r->rtuJack,r->rtuChan,t);
// т.к. с RTU188 свой обмен
// mbreg и mbfunc поля не используются
return true;
}
else else
{ {
dlog[Debug::CRIT] << myname << "(initRegInfo): Unknown mbtype='" << dev->dtype dlog[Debug::CRIT] << myname << "(initRegInfo): Unknown mbtype='" << dev->dtype
...@@ -2092,13 +1877,6 @@ bool MBExchange::initRTUDevice( RTUDevice* d, UniXML_iterator& it ) ...@@ -2092,13 +1877,6 @@ bool MBExchange::initRTUDevice( RTUDevice* d, UniXML_iterator& it )
} }
d->mbaddr = ModbusRTU::str2mbAddr(addr); d->mbaddr = ModbusRTU::str2mbAddr(addr);
if( d->dtype == MBExchange::dtRTU188 )
{
if( !d->rtu )
d->rtu = new RTUStorage(d->mbaddr);
}
return true; return true;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
...@@ -2111,7 +1889,7 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2111,7 +1889,7 @@ bool MBExchange::initItem( UniXML_iterator& it )
string addr = it.getProp(prop_prefix + "mbaddr"); string addr = it.getProp(prop_prefix + "mbaddr");
if( addr.empty() ) if( addr.empty() )
{ {
dlog[Debug::CRIT] << myname << "(initItem): Unknown mbaddr(" << prop_prefix << "mbaddr)='" << addr << "' for " << it.getProp("name") << endl; dlog[Debug::CRIT] << myname << "(initItem): Unknown mbaddr='" << addr << "' for " << it.getProp("name") << endl;
return false; return false;
} }
...@@ -2124,23 +1902,8 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2124,23 +1902,8 @@ bool MBExchange::initItem( UniXML_iterator& it )
return false; return false;
} }
ModbusRTU::ModbusData mbreg = 0; ModbusRTU::ModbusData mbreg;
int fn = it.getIntProp(prop_prefix + "mbfunc");
if( dev->dtype == dtRTU188 )
{
RegInfo r_tmp;
if( !initRTU188item(it, &r_tmp) )
{
dlog[Debug::CRIT] << myname << "(initItem): init RTU188 failed for " << it.getProp("name") << endl;
return false;
}
mbreg = RTUStorage::getRegister(r_tmp.rtuJack,r_tmp.rtuChan,p.stype);
fn = RTUStorage::getFunction(r_tmp.rtuJack,r_tmp.rtuChan,p.stype);
}
else
{
if( mbregFromID ) if( mbregFromID )
mbreg = p.si.id; // conf->getSensorID(it.getProp("name")); mbreg = p.si.id; // conf->getSensorID(it.getProp("name"));
else else
...@@ -2148,22 +1911,13 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2148,22 +1911,13 @@ bool MBExchange::initItem( UniXML_iterator& it )
string reg = it.getProp(prop_prefix + "mbreg"); string reg = it.getProp(prop_prefix + "mbreg");
if( reg.empty() ) if( reg.empty() )
{ {
dlog[Debug::CRIT] << myname << "(initItem): unknown mbreg(" << prop_prefix << ") for " << it.getProp("name") << endl; dlog[Debug::CRIT] << myname << "(initItem): unknown mbreg for " << it.getProp("name") << endl;
return false; return false;
} }
mbreg = ModbusRTU::str2mbData(reg); mbreg = ModbusRTU::str2mbData(reg);
} }
if( p.nbit != -1 ) int fn = it.getIntProp(prop_prefix + "mbfunc");
{
if( fn == ModbusRTU::fnReadCoilStatus || fn == ModbusRTU::fnReadInputStatus )
{
dlog[Debug::CRIT] << myname << "(initItem): MISMATCHED CONFIGURATION! nbit=" << p.nbit << " func=" << fn
<< " for " << it.getProp("name") << endl;
return false;
}
}
}
// формула для вычисления ID // формула для вычисления ID
// требования: // требования:
...@@ -2338,11 +2092,11 @@ bool MBExchange::initItem( UniXML_iterator& it ) ...@@ -2338,11 +2092,11 @@ bool MBExchange::initItem( UniXML_iterator& it )
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
bool MBExchange::initMTRitem( UniXML_iterator& it, RegInfo* p ) bool MBExchange::initMTRitem( UniXML_iterator& it, RegInfo* p )
{ {
p->mtrType = MTR::str2type(it.getProp(prop_prefix + "mtrtype")); p->mtrType = MTR::str2type(it.getProp("mtrtype"));
if( p->mtrType == MTR::mtUnknown ) if( p->mtrType == MTR::mtUnknown )
{ {
dlog[Debug::CRIT] << myname << "(readMTRItem): Unknown mtrtype '" dlog[Debug::CRIT] << myname << "(readMTRItem): Unknown mtrtype '"
<< it.getProp(prop_prefix + "mtrtype") << it.getProp("mtrtype")
<< "' for " << it.getProp("name") << endl; << "' for " << it.getProp("name") << endl;
return false; return false;
...@@ -2351,41 +2105,6 @@ bool MBExchange::initMTRitem( UniXML_iterator& it, RegInfo* p ) ...@@ -2351,41 +2105,6 @@ bool MBExchange::initMTRitem( UniXML_iterator& it, RegInfo* p )
return true; return true;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
bool MBExchange::initRTU188item( UniXML_iterator& it, RegInfo* p )
{
string jack(it.getProp(prop_prefix + "jack"));
string chan(it.getProp(prop_prefix + "channel"));
if( jack.empty() )
{
dlog[Debug::CRIT] << myname << "(readRTU188Item): Unknown " << prop_prefix << "jack='' "
<< " for " << it.getProp("name") << endl;
return false;
}
p->rtuJack = RTUStorage::s2j(jack);
if( p->rtuJack == RTUStorage::nUnknown )
{
dlog[Debug::CRIT] << myname << "(readRTU188Item): Unknown " << prop_prefix << "jack=" << jack
<< " for " << it.getProp("name") << endl;
return false;
}
if( chan.empty() )
{
dlog[Debug::CRIT] << myname << "(readRTU188Item): Unknown channel='' "
<< " for " << it.getProp("name") << endl;
return false;
}
p->rtuChan = UniSetTypes::uni_atoi(chan);
if( dlog.debugging(Debug::LEVEL2) )
dlog[Debug::LEVEL2] << myname << "(readRTU188Item): add jack='" << jack << "'"
<< " channel='" << p->rtuChan << "'" << endl;
return true;
}
// ------------------------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, const MBExchange::DeviceType& dt ) std::ostream& operator<<( std::ostream& os, const MBExchange::DeviceType& dt )
{ {
switch(dt) switch(dt)
...@@ -2432,11 +2151,7 @@ std::ostream& operator<<( std::ostream& os, const MBExchange::RSProperty& p ) ...@@ -2432,11 +2151,7 @@ std::ostream& operator<<( std::ostream& os, const MBExchange::RSProperty& p )
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MBExchange::initDeviceList() void MBExchange::initDeviceList()
{ {
xmlNode* respNode = 0; xmlNode* respNode = conf->findNode(cnode,"DeviceList");
UniXML* xml = conf->getConfXML();
if( xml )
respNode = xml->extFindNode(cnode,1,1,"DeviceList");
if( respNode ) if( respNode )
{ {
UniXML_iterator it1(respNode); UniXML_iterator it1(respNode);
...@@ -2475,25 +2190,7 @@ bool MBExchange::initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXM ...@@ -2475,25 +2190,7 @@ bool MBExchange::initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXM
d->second->resp_id = conf->getSensorID(s); d->second->resp_id = conf->getSensorID(s);
if( d->second->resp_id == DefaultObjectId ) if( d->second->resp_id == DefaultObjectId )
{ {
dlog[Debug::CRIT] << myname << "(initDeviceInfo): not found ID for respondSensor=" << s << endl; dlog[Debug::CRIT] << myname << "(initDeviceInfo): not found ID for noRespondSensor=" << s << endl;
return false;
}
}
string mod(it.getProp("modeSensor"));
if( !mod.empty() )
{
d->second->mode_id = conf->getSensorID(mod);
if( d->second->mode_id == DefaultObjectId )
{
dlog[Debug::CRIT] << myname << "(initDeviceInfo): not found ID for modeSensor=" << mod << endl;
return false;
}
UniversalIO::IOTypes m_iotype = conf->getIOType(d->second->mode_id);
if( m_iotype != UniversalIO::AnalogInput )
{
dlog[Debug::CRIT] << myname << "(initDeviceInfo): modeSensor='" << mod << "' must be 'AI'" << endl;
return false; return false;
} }
} }
...@@ -2615,8 +2312,6 @@ void MBExchange::sysCommand( UniSetTypes::SystemMessage *sm ) ...@@ -2615,8 +2312,6 @@ void MBExchange::sysCommand( UniSetTypes::SystemMessage *sm )
initOutput(); initOutput();
} }
updateSM();
askTimer(tmExchange,polltime); askTimer(tmExchange,polltime);
break; break;
} }
...@@ -2641,6 +2336,7 @@ void MBExchange::sysCommand( UniSetTypes::SystemMessage *sm ) ...@@ -2641,6 +2336,7 @@ void MBExchange::sysCommand( UniSetTypes::SystemMessage *sm )
if( !force ) if( !force )
{ {
uniset_mutex_lock l(pollMutex,2000);
force = true; force = true;
poll(); poll();
force = false; force = false;
...@@ -2691,6 +2387,9 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd ) ...@@ -2691,6 +2387,9 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd )
throw SystemError(err.str()); throw SystemError(err.str());
} }
if( force_out )
return;
try try
{ {
if( sidExchangeMode != DefaultObjectId ) if( sidExchangeMode != DefaultObjectId )
...@@ -2708,24 +2407,6 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd ) ...@@ -2708,24 +2407,6 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd )
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 ) for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
try
{
if( d->mode_id != DefaultObjectId )
shm->askSensor(d->mode_id,cmd);
}
catch( UniSetTypes::Exception& ex )
{
dlog[Debug::WARN] << myname << "(askSensors): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::WARN] << myname << "(askSensors): (mode_id=" << d->mode_id << ").. catch..." << std::endl;
}
if( force_out )
return;
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it ) for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{ {
if( !isWriteFunction(it->second->mbfunc) ) if( !isWriteFunction(it->second->mbfunc) )
...@@ -2743,7 +2424,7 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd ) ...@@ -2743,7 +2424,7 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd )
} }
catch(...) catch(...)
{ {
dlog[Debug::WARN] << myname << "(askSensors): id=" << i->si.id << " catch..." << std::endl; dlog[Debug::WARN] << myname << "(askSensors): catch..." << std::endl;
} }
} }
} }
...@@ -2752,24 +2433,20 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd ) ...@@ -2752,24 +2433,20 @@ void MBExchange::askSensors( UniversalIO::UIOCommand cmd )
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void MBExchange::sensorInfo( UniSetTypes::SensorMessage* sm ) void MBExchange::sensorInfo( UniSetTypes::SensorMessage* sm )
{ {
if( force_out )
return;
if( sm->id == sidExchangeMode ) if( sm->id == sidExchangeMode )
{ {
exchangeMode = sm->value; exchangeMode = sm->value;
if( dlog.debugging(Debug::LEVEL3) ) if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(sensorInfo): exchange MODE=" << sm->value << std::endl; dlog[Debug::LEVEL3] << myname << "(sensorInfo): exchange MODE=" << sm->value << std::endl;
//return; // этот датчик может встречаться и в списке обмена.. поэтому делать return нельзя. return;
} }
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 ) for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
if( sm->id == d->mode_id )
d->mode = sm->value;
if( force_out )
continue;
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it ) for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{ {
if( !isWriteFunction(it->second->mbfunc) ) if( !isWriteFunction(it->second->mbfunc) )
...@@ -2834,7 +2511,7 @@ void MBExchange::poll() ...@@ -2834,7 +2511,7 @@ void MBExchange::poll()
} }
{ {
uniset_mutex_lock l(pollMutex,200); uniset_mutex_lock l(pollMutex);
pollActivated = true; pollActivated = true;
ptTimeout.reset(); ptTimeout.reset();
} }
...@@ -2845,17 +2522,12 @@ void MBExchange::poll() ...@@ -2845,17 +2522,12 @@ void MBExchange::poll()
if( !checkProcActive() ) if( !checkProcActive() )
return; return;
bool allNotRespond = true;
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 ) for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
if( d->mode_id != DefaultObjectId && d->mode == emSkipExchange ) if( dlog.debugging(Debug::INFO) )
continue; dlog[Debug::INFO] << myname << "(poll): ask addr=" << ModbusRTU::addr2str(d->mbaddr)
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(poll): ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " regs=" << d->regmap.size() << endl; << " regs=" << d->regmap.size() << endl;
d->resp_real = false; d->resp_real = false;
...@@ -2889,13 +2561,11 @@ void MBExchange::poll() ...@@ -2889,13 +2561,11 @@ void MBExchange::poll()
if( ex.err == ModbusRTU::erTimeOut && !d->ask_every_reg ) if( ex.err == ModbusRTU::erTimeOut && !d->ask_every_reg )
break; break;
if( ex.err == ModbusRTU::erNoError ) // если контроллер хоть что-то ответил, то вроде как связь есть..
if( ex.err != ModbusRTU::erTimeOut )
d->resp_real = true; d->resp_real = true;
} }
if( d->resp_real )
allNotRespond = false;
if( it==d->regmap.end() ) if( it==d->regmap.end() )
break; break;
...@@ -2915,7 +2585,7 @@ void MBExchange::poll() ...@@ -2915,7 +2585,7 @@ void MBExchange::poll()
} }
{ {
uniset_mutex_lock l(pollMutex,120); uniset_mutex_lock l(pollMutex);
pollActivated = false; pollActivated = false;
} }
...@@ -2926,128 +2596,20 @@ void MBExchange::poll() ...@@ -2926,128 +2596,20 @@ void MBExchange::poll()
updateSM(); updateSM();
// check thresholds // check thresholds
for( ThresholdList::iterator t=thrlist.begin(); t!=thrlist.end(); ++t )
{
if( !checkProcActive() )
return;
IOBase::processingThreshold(&(*t),shm,force);
}
if( trReopen.hi(allNotRespond) )
ptReopen.reset();
if( allNotRespond && ptReopen.checkTime() )
{
uniset_mutex_lock l(pollMutex, 300);
if( dlog.debugging(Debug::WARN) )
dlog[Debug::WARN] << myname << ": REOPEN timeout..(" << ptReopen.getInterval() << ")" << endl;
mb = initMB(true);
ptReopen.reset();
}
// printMap(rmap);
}
// -----------------------------------------------------------------------------
bool MBExchange::RTUDevice::checkRespond()
{
bool prev = resp_state;
if( resp_ptTimeout.getInterval() <= 0 )
{
resp_state = resp_real;
return (prev != resp_state);
}
if( resp_trTimeout.hi(resp_state && !resp_real) )
resp_ptTimeout.reset();
if( resp_real )
resp_state = true;
else if( resp_state && !resp_real && resp_ptTimeout.checkTime() )
resp_state = false;
// если ещё не инициализировали значение в SM
// то возвращаем true, чтобы оно принудительно сохранилось
if( !resp_init )
{
resp_state = resp_real;
resp_init = true;
prev = resp_state;
return true;
}
return ( prev != resp_state );
}
// -----------------------------------------------------------------------------
void MBExchange::updateRespondSensors()
{
bool chanTimeout = false;
{
uniset_mutex_lock l(pollMutex,240);
chanTimeout = pollActivated && ptTimeout.checkTime();
}
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 ) for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
if( chanTimeout )
it1->second->resp_real = false;
if( dlog.debugging(Debug::LEVEL4) )
{
dlog[Debug::LEVEL4] << myname << ": check respond addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " respond_id=" << d->resp_id
<< " real=" << d->resp_real
<< " state=" << d->resp_state
<< endl;
}
if( d->checkRespond() && d->resp_id != DefaultObjectId )
{
try
{
bool set = d->resp_invert ? !d->resp_state : d->resp_state;
shm->localSaveState(d->resp_dit,d->resp_id,set,getId());
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << myname << "(step): (respond) " << ex << std::endl;
}
}
}
}
// -----------------------------------------------------------------------------
void MBExchange::execute()
{
no_extimer = true;
try
{ {
askTimer(tmExchange,0); if( !checkProcActive() )
} return;
catch(...){}
initMB(false);
while(1) RegInfo* r(it->second);
{ for( PList::iterator i=r->slst.begin(); i!=r->slst.end(); ++i )
try IOBase::processingThreshold( &(*i),shm,force);
{
step();
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << myname << "(execute): " << ex << std::endl;
} }
catch(...)
{
dlog[Debug::CRIT] << myname << "(execute): catch ..." << endl;
} }
msleep(polltime); // printMap(rmap);
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -111,9 +111,9 @@ void RTUStorage::poll( ModbusRTUMaster* mb ) ...@@ -111,9 +111,9 @@ void RTUStorage::poll( ModbusRTUMaster* mb )
// ----------------------------------- // -----------------------------------
} }
// опрос UNIO48 DO
if( pollUNIO ) if( pollUNIO )
{ {
// опрос UNIO48 DO
{ {
ModbusRTU::ReadCoilRetMessage ret = mb->read01( addr,16,48 ); ModbusRTU::ReadCoilRetMessage ret = mb->read01( addr,16,48 );
ModbusRTU::DataBits bits; ModbusRTU::DataBits bits;
...@@ -179,7 +179,7 @@ float RTUStorage::getFloat( RTUJack jack, unsigned short int chan, UniversalIO:: ...@@ -179,7 +179,7 @@ float RTUStorage::getFloat( RTUJack jack, unsigned short int chan, UniversalIO::
case nJ1: case nJ1:
return unio_ai[chan]; return unio_ai[chan];
case nJ2: case nJ2:
return unio_ai[12+chan]; return unio_ai[24+chan];
case nJ5: case nJ5:
return dio_ai[chan]; return dio_ai[chan];
case nX1: case nX1:
...@@ -201,7 +201,7 @@ float RTUStorage::getFloat( RTUJack jack, unsigned short int chan, UniversalIO:: ...@@ -201,7 +201,7 @@ float RTUStorage::getFloat( RTUJack jack, unsigned short int chan, UniversalIO::
case nJ1: case nJ1:
return unio_ao[chan]; return unio_ao[chan];
case nJ2: case nJ2:
return unio_ao[12+chan]; return unio_ao[24+chan];
case nJ5: case nJ5:
return dio_ao[chan]; return dio_ao[chan];
case nX1: case nX1:
...@@ -353,84 +353,6 @@ ModbusRTU::ModbusData RTUStorage::getRegister( RTUJack jack, unsigned short chan ...@@ -353,84 +353,6 @@ ModbusRTU::ModbusData RTUStorage::getRegister( RTUJack jack, unsigned short chan
return -1; return -1;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
ModbusRTU::SlaveFunctionCode RTUStorage::getFunction( RTUJack jack, unsigned short chan, UniversalIO::IOTypes t )
{
if( t == UniversalIO::AnalogInput )
{
switch( jack )
{
case nJ1:
case nJ2:
case nJ5:
case nX1:
case nX2:
return ModbusRTU::fnReadInputRegisters;
default:
break;
}
return ModbusRTU::fnUnknown;
}
if( t == UniversalIO::AnalogOutput )
{
switch( jack )
{
case nJ1:
case nJ2:
case nJ5:
return ModbusRTU::fnReadOutputRegisters;
case nX1:
case nX2:
return ModbusRTU::fnReadInputRegisters;
default:
break;
}
return ModbusRTU::fnUnknown;
}
if( t == UniversalIO::DigitalInput )
{
switch( jack )
{
case nJ1:
case nJ2:
case nJ5:
case nX4:
case nX5:
return ModbusRTU::fnReadInputStatus;
default:
break;
}
return ModbusRTU::fnUnknown;
}
if( t == UniversalIO::DigitalOutput )
{
switch( jack )
{
case nJ1:
case nJ2:
case nJ5:
return ModbusRTU::fnReadCoilStatus;
default:
break;
}
return ModbusRTU::fnUnknown;
}
return ModbusRTU::fnUnknown;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, RTUStorage& m ) std::ostream& operator<<(std::ostream& os, RTUStorage& m )
{ {
os << "-------------------" << endl os << "-------------------" << endl
...@@ -559,22 +481,22 @@ void RTUStorage::print() ...@@ -559,22 +481,22 @@ void RTUStorage::print()
cout << this; cout << this;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
RTUStorage::RTUJack RTUStorage::s2j( const std::string& jack ) RTUStorage::RTUJack RTUStorage::s2j( const std::string jack )
{ {
if( jack == "J1" || jack == "j1" ) if( jack == "J1" )
return nJ1; return nJ1;
if( jack == "J2" || jack == "j2" ) if( jack == "J2" )
return nJ2; return nJ2;
if( jack == "J5" || jack == "j5" ) if( jack == "J5" )
return nJ5; return nJ5;
if( jack == "X1" || jack == "x1" ) if( jack == "X1" )
return nX1; return nX1;
if( jack == "X2" || jack == "x2" ) if( jack == "X2" )
return nX2; return nX2;
if( jack == "X4" || jack == "x4" ) if( jack == "X4" )
return nX4; return nX4;
if( jack == "X5" || jack == "x5" ) if( jack == "X5" )
return nX5; return nX5;
return nUnknown; return nUnknown;
......
...@@ -38,7 +38,7 @@ class RTUStorage ...@@ -38,7 +38,7 @@ class RTUStorage
nX5 // DI (8) nX5 // DI (8)
}; };
static RTUJack s2j( const std::string& jack ); static RTUJack s2j( const std::string jack );
static std::string j2s( RTUJack j ); static std::string j2s( RTUJack j );
long getInt( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t ); long getInt( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t );
...@@ -47,8 +47,6 @@ class RTUStorage ...@@ -47,8 +47,6 @@ class RTUStorage
static ModbusRTU::ModbusData getRegister( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t ); static ModbusRTU::ModbusData getRegister( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t );
static ModbusRTU::SlaveFunctionCode getFunction( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t );
// ДОДЕЛАТЬ: setState, setValue // ДОДЕЛАТЬ: setState, setValue
void print(); void print();
......
...@@ -8,16 +8,18 @@ libUniSetRTU_la_LDFLAGS = -version-info $(URTU_VER) ...@@ -8,16 +8,18 @@ libUniSetRTU_la_LDFLAGS = -version-info $(URTU_VER)
libUniSetRTU_la_LIBADD = $(top_builddir)/lib/libUniSet.la \ libUniSetRTU_la_LIBADD = $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \ $(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \ $(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(top_builddir)/extensions/ModbusMaster/libMBMaster.la \
$(SIGC_LIBS) $(SIGC_LIBS)
libUniSetRTU_la_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) libUniSetRTU_la_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory -I$(top_builddir)/extensions/ModbusMaster $(SIGC_CFLAGS)
libUniSetRTU_la_SOURCES = RTUStorage.cc RTUExchange.cc libUniSetRTU_la_SOURCES = RTUExchange.cc
@PACKAGE@_rtuexchange_SOURCES = rtuexchange.cc @PACKAGE@_rtuexchange_SOURCES = rtuexchange.cc
@PACKAGE@_rtuexchange_LDADD = libUniSetRTU.la $(top_builddir)/lib/libUniSet.la \ @PACKAGE@_rtuexchange_LDADD = libUniSetRTU.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \ $(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \ $(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(top_builddir)/extensions/ModbusMaster/libMBMaster.la \
$(SIGC_LIBS) $(SIGC_LIBS)
@PACKAGE@_rtuexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) @PACKAGE@_rtuexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory -I$(top_builddir)/extensions/ModbusMaster $(SIGC_CFLAGS)
@PACKAGE@_mtr_conv_SOURCES = mtrconv.cc @PACKAGE@_mtr_conv_SOURCES = mtrconv.cc
@PACKAGE@_mtr_conv_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la @PACKAGE@_mtr_conv_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la
...@@ -31,8 +33,10 @@ libUniSetRTU_la_SOURCES = RTUStorage.cc RTUExchange.cc ...@@ -31,8 +33,10 @@ libUniSetRTU_la_SOURCES = RTUStorage.cc RTUExchange.cc
@PACKAGE@_vtconv_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la @PACKAGE@_vtconv_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la
@PACKAGE@_vtconv_CXXFLAGS = -I$(top_builddir)/extensions/include @PACKAGE@_vtconv_CXXFLAGS = -I$(top_builddir)/extensions/include
@PACKAGE@_rtu188_state_LDADD = libUniSetRTU.la $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la @PACKAGE@_rtu188_state_LDADD = libUniSetRTU.la \
@PACKAGE@_rtu188_state__CXXFLAGS = -I$(top_builddir)/extensions/include $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/ModbusMaster/libMBMaster.la
@PACKAGE@_rtu188_state_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/ModbusMaster
@PACKAGE@_rtu188_state_SOURCES = rtustate.cc @PACKAGE@_rtu188_state_SOURCES = rtustate.cc
# install # install
......
// -----------------------------------------------------------------------------
#include <cmath>
#include <iostream>
#include <iomanip>
#include <string>
#include "modbus/ModbusRTUMaster.h"
#include "RTUStorage.h"
// -----------------------------------------------------------------------------
using namespace std;
// -----------------------------------------------------------------------------
RTUStorage::RTUStorage( ModbusRTU::ModbusAddr a ):
addr(a),
pingOK(false),
pollADC(true),
pollDI(true),
pollDIO(true),
pollUNIO(true)
{
memset(adc,0,sizeof(adc));
memset(di,0,sizeof(di));
memset(dio_do,0,sizeof(dio_do));
memset(dio_di,0,sizeof(dio_di));
memset(dio_ai,0,sizeof(dio_ai));
memset(dio_ao,0,sizeof(dio_ao));
memset(unio_di,0,sizeof(unio_di));
memset(unio_do,0,sizeof(unio_do));
memset(unio_ai,0,sizeof(unio_ai));
memset(unio_ao,0,sizeof(unio_ao));
}
// -----------------------------------------------------------------------------
RTUStorage::~RTUStorage()
{
}
// -----------------------------------------------------------------------------
void RTUStorage::poll( ModbusRTUMaster* mb )
throw( ModbusRTU::mbException )
{
try
{
pingOK = true;
// опрос АЦП
if( pollADC )
{
ModbusRTU::ReadInputRetMessage ret = mb->read04( addr,1016, 16 );
for( int i=0,k=0; i<16; i+=2,k++ )
adc[k] = ModbusRTU::dat2f(ret.data[i],ret.data[i+1]);
}
// -----------------------------------
// опрос 16 DI
if( pollDI )
{
ModbusRTU::ReadInputStatusRetMessage ret = mb->read02( addr,0,16 );
ModbusRTU::DataBits bits;
for( int b=0; b<2; b++ )
{
if( ret.getData(b,bits) )
{
for( int i=0; i<8; i++ )
di[i+8*b] = bits[i];
}
}
}
// -----------------------------------
// опрос 16DIO DO
if( pollDIO )
{
{
ModbusRTU::ReadCoilRetMessage ret = mb->read01( addr,0,16 );
ModbusRTU::DataBits bits;
for( int b=0; b<2; b++ )
{
if( ret.getData(b,bits) )
{
for( int i=0; i<8; i++ )
dio_do[i+8*b] = bits[i];
}
}
}
// -----------------------------------
// опрос 16DIO DI
{
ModbusRTU::ReadInputStatusRetMessage ret = mb->read02( addr,16,16 );
ModbusRTU::DataBits bits;
for( int b=0; b<2; b++ )
{
if( ret.getData(b,bits) )
{
for( int i=0; i<8; i++ )
dio_di[i+8*b] = bits[i];
}
}
}
// -----------------------------------
// опрос 16DIO AI
{
ModbusRTU::ReadInputRetMessage ret = mb->read04( addr, 1000, 16 );
int k = 0;
for( int i=0; i<16; i+=2,k++ )
dio_ai[k] = ModbusRTU::dat2f(ret.data[i],ret.data[i+1]);
}
// -----------------------------------
// опрос 16DIO AO
{
ModbusRTU::ReadOutputRetMessage ret = mb->read03( addr, 1000, 16 );
int k = 0;
for( int i=0; i<16; i+=2,k++ )
dio_ao[k] = ModbusRTU::dat2f(ret.data[i],ret.data[i+1]);
}
// -----------------------------------
}
// опрос UNIO48 DO
if( pollUNIO )
{
{
ModbusRTU::ReadCoilRetMessage ret = mb->read01( addr,16,48 );
ModbusRTU::DataBits bits;
for( int b=0; b<8; b++ )
{
if( ret.getData(b,bits) )
{
for( int i=0; i<8; i++ )
unio_do[i+8*b] = bits[i];
}
}
}
// -----------------------------------
// опрос UNIO48 DI
{
ModbusRTU::ReadInputStatusRetMessage ret = mb->read02( addr,32,48 );
ModbusRTU::DataBits bits;
for( int b=0; b<8; b++ )
{
if( ret.getData(b,bits) )
{
for( int i=0; i<8; i++ )
unio_di[i+8*b] = bits[i];
}
}
}
// -----------------------------------
// опрос UNIO48 AI
{
ModbusRTU::ReadInputRetMessage ret = mb->read04( addr, 1032, 48 );
int k = 0;
for( int i=0; i<48; i+=2,k++ )
unio_ai[k] = ModbusRTU::dat2f(ret.data[i],ret.data[i+1]);
}
// -----------------------------------
// опрос UNIO48 AO
{
ModbusRTU::ReadOutputRetMessage ret = mb->read03( addr, 1016, 48 );
int k = 0;
for( int i=0; i<48; i+=2,k++ )
unio_ao[k] = ModbusRTU::dat2f(ret.data[i],ret.data[i+1]);
}
}
}
catch(...)
{
pingOK = false;
throw;
}
}
// -----------------------------------------------------------------------------
long RTUStorage::getInt( RTUJack jack, unsigned short int chan, UniversalIO::IOTypes t )
{
return lroundf( getFloat(jack,chan,t) );
}
// -----------------------------------------------------------------------------
float RTUStorage::getFloat( RTUJack jack, unsigned short int chan, UniversalIO::IOTypes t )
{
if( t == UniversalIO::AnalogInput )
{
switch( jack )
{
case nJ1:
return unio_ai[chan];
case nJ2:
return unio_ai[24+chan];
case nJ5:
return dio_ai[chan];
case nX1:
return adc[chan];
case nX2:
return adc[4+chan];
default:
break;
}
return 0;
}
if( t == UniversalIO::AnalogOutput )
{
switch( jack )
{
case nJ1:
return unio_ao[chan];
case nJ2:
return unio_ao[24+chan];
case nJ5:
return dio_ao[chan];
case nX1:
return adc[chan];
case nX2:
return adc[4+chan];
default:
break;
}
return 0;
}
return 0;
}
// -----------------------------------------------------------------------------
bool RTUStorage::getState( RTUJack jack, unsigned short int chan, UniversalIO::IOTypes t )
{
if( t == UniversalIO::DigitalInput )
{
switch( jack )
{
case nJ1:
return unio_di[chan];
case nJ2:
return unio_di[24+chan];
case nJ5:
return dio_di[chan];
case nX4:
return di[chan];
case nX5:
return di[8+chan];
default:
break;
}
return false;
}
if( t == UniversalIO::DigitalOutput )
{
switch( jack )
{
case nJ1:
return unio_do[chan];
case nJ2:
return unio_do[24+chan];
case nJ5:
return dio_do[chan];
default:
break;
}
return false;
}
return false;
}
// -----------------------------------------------------------------------------
ModbusRTU::ModbusData RTUStorage::getRegister( RTUJack jack, unsigned short chan, UniversalIO::IOTypes t )
{
if( t == UniversalIO::AnalogInput )
{
switch( jack )
{
case nJ1:
return 1032+chan;
case nJ2:
return 1032+24+chan;
case nJ5:
return 1000+chan;
case nX1:
return 1016+chan;
case nX2:
return 1016+4+chan;
default:
break;
}
return -1;
}
if( t == UniversalIO::AnalogOutput )
{
switch( jack )
{
case nJ1:
return 1016+chan;
case nJ2:
return 1016+24+chan;
case nJ5:
return 1000+chan;
case nX1:
return 1016+chan;
case nX2:
return 1016+4+chan;
default:
break;
}
return -1;
}
if( t == UniversalIO::DigitalInput )
{
switch( jack )
{
case nJ1:
return 32+chan;
case nJ2:
return 32+24+chan;
case nJ5:
return 16+chan;
case nX4:
return chan;
case nX5:
return 8+chan;
default:
break;
}
return -1;
}
if( t == UniversalIO::DigitalOutput )
{
switch( jack )
{
case nJ1:
return 16+chan;
case nJ2:
return 16+24+chan;
case nJ5:
return chan;
default:
break;
}
return -1;
}
return -1;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, RTUStorage& m )
{
os << "-------------------" << endl
<< " АЦП (8 каналов): " << endl;
for( int i=0; i<8; i++ ) // номера каналов
os << setw(12) << i << "|";
os << endl;
for( int i=0; i<8; i++ )
os << setw(12) << m.adc[i] << "|";
os << endl;
os << "-------------------" << endl
<< " DI (16 каналов): " << endl;
for( int i=0; i<16; i++ ) // номера каналов
os << setw(2) << i << "|";
os << endl;
for( int i=0; i<16; i++ )
os << setw(2) << m.di[i] << "|";
os << endl;
os << "-------------------" << endl
<< " DIO DO(16 каналов): " << endl;
for( int i=0; i<16; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=0; i<16; i++ )
os << setw(2) << m.dio_do[i] << " | ";
os << endl;
os << "-------------------" << endl
<< " DIO DI(16 каналов): " << endl;
for( int i=0; i<16; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=0; i<16; i++ )
os << setw(2) << m.dio_di[i] << " | ";
os << endl;
os << "-------------------" << endl
<< " DIO AI (16 каналов): " << endl;
for( int i=0; i<16; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=0; i<16; i++ )
os << setw(2) << m.dio_ai[i] << " | ";
os << endl;
os << "-------------------" << endl
<< " DIO AO (16 каналов): " << endl;
for( int i=0; i<16; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=0; i<16; i++ )
os << setw(2) << m.dio_ao[i] << " | ";
os << endl;
os << "-------------------" << endl
<< " UNIO48 DI: " << endl;
for( int i=0; i<24; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=0; i<24; i++ )
os << setw(2) << m.unio_di[i] << " | ";
os << endl;
for( int i=24; i<48; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=24; i<48; i++ )
os << setw(2) << m.unio_di[i] << " | ";
os << endl;
os << "-------------------" << endl
<< " UNIO48 DO: " << endl;
for( int i=0; i<24; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=0; i<24; i++ )
os << setw(2) << m.unio_do[i] << " | ";
os << endl;
for( int i=24; i<48; i++ ) // номера каналов
os << setw(2) << i << " | ";
os << endl;
for( int i=24; i<48; i++ )
os << setw(2) << m.unio_do[i] << " | ";
os << endl;
os << "-------------------" << endl
<< " UNIO48 AI: " << endl;
for( int i=0; i<12; i++ ) // номера каналов
os << setw(6) << i << " | ";
os << endl;
for( int i=0; i<12; i++ )
os << setw(6) << m.unio_ai[i] << " | ";
os << endl;
for( int i=12; i<24; i++ ) // номера каналов
os << setw(6) << i << " | ";
os << endl;
for( int i=12; i<24; i++ )
os << setw(6) << m.unio_ai[i] << " | ";
os << endl;
os << "-------------------" << endl
<< " UNIO48 AO: " << endl;
for( int i=0; i<12; i++ ) // номера каналов
os << setw(6) << i << " | ";
os << endl;
for( int i=0; i<12; i++ )
os << setw(6) << m.unio_ao[i] << " | ";
os << endl;
for( int i=12; i<24; i++ ) // номера каналов
os << setw(6) << i << " | ";
os << endl;
for( int i=12; i<24; i++ )
os << setw(6) << m.unio_ao[i] << " | ";
os << endl;
return os;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, RTUStorage* m )
{
return os << (*m);
}
// -----------------------------------------------------------------------------
void RTUStorage::print()
{
cout << this;
}
// -----------------------------------------------------------------------------
RTUStorage::RTUJack RTUStorage::s2j( const std::string jack )
{
if( jack == "J1" )
return nJ1;
if( jack == "J2" )
return nJ2;
if( jack == "J5" )
return nJ5;
if( jack == "X1" )
return nX1;
if( jack == "X2" )
return nX2;
if( jack == "X4" )
return nX4;
if( jack == "X5" )
return nX5;
return nUnknown;
}
// -----------------------------------------------------------------------------
std::string RTUStorage::j2s( RTUStorage::RTUJack jack )
{
if( jack == nJ1 )
return "J1";
if( jack == nJ2 )
return "J2";
if( jack == nJ5 )
return "J5";
if( jack == nX1 )
return "X1";
if( jack == nX2 )
return "X2";
if( jack == nX4 )
return "X4";
if( jack == nX5 )
return "X5";
return "";
}
// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------
#ifndef _RTUSTORAGE_H_
#define _RTUSTORAGE_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include "modbus/ModbusTypes.h"
#include "UniSetTypes.h"
// -----------------------------------------------------------------------------
class ModbusRTUMaster;
// -----------------------------------------------------------------------------
class RTUStorage
{
public:
RTUStorage( ModbusRTU::ModbusAddr addr );
~RTUStorage();
void poll( ModbusRTUMaster* mb )
throw(ModbusRTU::mbException);
inline ModbusRTU::ModbusAddr getAddress(){ return addr; }
inline bool ping(){ return pingOK; }
inline void setPollADC( bool set ){ pollADC = set; }
inline void setPollDI( bool set ){ pollDI = set; }
inline void setPollDIO( bool set ){ pollDIO = set; }
inline void setPollUNIO( bool set ){ pollUNIO = set; }
enum RTUJack
{
nUnknown,
nJ1, // UNIO48 (FPGA0)
nJ2, // UNIO48 (FPGA1)
nJ5, // DIO 16
nX1, // АЦП (8)
nX2, // АЦП (8)
nX4, // DI (8)
nX5 // DI (8)
};
static RTUJack s2j( const std::string jack );
static std::string j2s( RTUJack j );
long getInt( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t );
float getFloat( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t );
bool getState( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t );
static ModbusRTU::ModbusData getRegister( RTUJack jack, unsigned short channel, UniversalIO::IOTypes t );
// ДОДЕЛАТЬ: setState, setValue
void print();
friend std::ostream& operator<<(std::ostream& os, RTUStorage& m );
friend std::ostream& operator<<(std::ostream& os, RTUStorage* m );
protected:
ModbusRTU::ModbusAddr addr;
bool pingOK;
bool pollADC;
bool pollDI;
bool pollDIO;
bool pollUNIO;
float adc[8]; // АЦП
bool di[16]; // Порт 16DI
bool dio_do[16]; // Порт 16DIO DO
bool dio_di[16]; // Порт 16DIO DI
float dio_ai[16]; // Порт 16DIO AI
float dio_ao[16]; // Порт 16DIO AO
bool unio_do[48]; // Порт UNIO48 DO
bool unio_di[48]; // Порт UNIO48 DI
float unio_ai[24]; // Порт UNIO48 AI
float unio_ao[24]; // Порт UNIO48 AO
};
// --------------------------------------------------------------------------
#endif // _RTUSTORAGE_H_
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
#include <cmath>
#include <limits>
#include <sstream>
#include <Exceptions.h>
#include <extensions/Extensions.h>
#include "MBExchange.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
MBExchange::MBExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId,
SharedMemory* ic, const std::string prefix ):
UniSetObject_LT(objId),
allInitOK(false),
shm(0),
initPause(0),
force(false),
force_out(false),
mbregFromID(false),
sidExchangeMode(DefaultObjectId),
activated(false),
noQueryOptimization(false),
no_extimer(false),
prefix(prefix),
poll_count(0),
prop_prefix(""),
mb(0),
pollActivated(false)
{
// cout << "$ $" << endl;
if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(MBExchange): objId=-1?!! Use --" + prefix + "-name" );
// xmlNode* cnode = conf->getNode(myname);
string conf_name = conf->getArgParam("--" + prefix + "-confnode",myname);
cnode = conf->getNode(conf_name);
if( cnode == NULL )
throw UniSetTypes::SystemError("(MBExchange): Not found node <" + conf_name + " ...> for " + myname );
shm = new SMInterface(shmId,&ui,objId,ic);
UniXML_iterator it(cnode);
// определяем фильтр
s_field = conf->getArgParam("--" + prefix + "-filter-field");
s_fvalue = conf->getArgParam("--" + prefix + "-filter-value");
dlog[Debug::INFO] << myname << "(init): read fileter-field='" << s_field
<< "' filter-value='" << s_fvalue << "'" << endl;
stat_time = conf->getArgPInt("--" + prefix + "-statistic-sec",it.getProp("statistic_sec"),0);
if( stat_time > 0 )
ptStatistic.setTiming(stat_time*1000);
// recv_timeout = conf->getArgPInt("--" + prefix + "-recv-timeout",it.getProp("recv_timeout"), 500);
//
// int tout = conf->getArgPInt("--" + prefix + "-timeout",it.getProp("timeout"), 5000);
// ptTimeout.setTiming(tout);
noQueryOptimization = conf->getArgInt("--" + prefix + "-no-query-optimization",it.getProp("no_query_optimization"));
mbregFromID = conf->getArgInt("--" + prefix + "-reg-from-id",it.getProp("reg_from_id"));
dlog[Debug::INFO] << myname << "(init): mbregFromID=" << mbregFromID << endl;
polltime = conf->getArgPInt("--" + prefix + "-polltime",it.getProp("polltime"), 100);
initPause = conf->getArgPInt("--" + prefix + "-initPause",it.getProp("initPause"), 3000);
sleepPause_usec = conf->getArgPInt("--" + prefix + "-sleepPause-usec",it.getProp("slepePause"), 100);
force = conf->getArgInt("--" + prefix + "-force",it.getProp("force"));
force_out = conf->getArgInt("--" + prefix + "-force-out",it.getProp("force_out"));
// ********** HEARTBEAT *************
string heart = conf->getArgParam("--" + prefix + "-heartbeat-id",it.getProp("heartbeat_id"));
if( !heart.empty() )
{
sidHeartBeat = conf->getSensorID(heart);
if( sidHeartBeat == DefaultObjectId )
{
ostringstream err;
err << myname << ": ID not found ('HeartBeat') for " << heart;
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
int heartbeatTime = getHeartBeatTime();
if( heartbeatTime )
ptHeartBeat.setTiming(heartbeatTime);
else
ptHeartBeat.setTiming(UniSetTimer::WaitUpTime);
maxHeartBeat = conf->getArgPInt("--" + prefix + "-heartbeat-max",it.getProp("heartbeat_max"), 10);
test_id = sidHeartBeat;
}
else
{
test_id = conf->getSensorID("TestMode_S");
if( test_id == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): test_id unknown. 'TestMode_S' not found...";
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl;
string emode = conf->getArgParam("--" + prefix + "-exchange-mode-id",it.getProp("exchangeModeID"));
if( !emode.empty() )
{
sidExchangeMode = conf->getSensorID(emode);
if( sidExchangeMode == DefaultObjectId )
{
ostringstream err;
err << myname << ": ID not found ('ExchangeMode') for " << emode;
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
activateTimeout = conf->getArgPInt("--" + prefix + "-activate-timeout", 20000);
}
// -----------------------------------------------------------------------------
void MBExchange::help_print( int argc, const char* const* argv )
{
cout << "--prefix-name name - ObjectId (имя) процесса. По умолчанию: MBExchange1" << endl;
cout << "--prefix-confnode name - Настроечная секция в конф. файле <name>. " << endl;
cout << "--prefix-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек." << endl;
cout << "--prefix-heartbeat-id name - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl;
cout << "--prefix-heartbeat-max val - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--prefix-ready-timeout msec - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--prefix-force 0,1 - Сохранять значения в SM, независимо от, того менялось ли значение" << endl;
cout << "--prefix-force-out 0,1 - Считывать значения 'выходов' кажый раз SM (а не по изменению)" << endl;
cout << "--prefix-initPause msec - Задержка перед инициализацией (время на активизация процесса)" << endl;
cout << "--prefix-no-query-optimization 0,1 - Не оптимизировать запросы (не объединять соседние регистры в один запрос)" << endl;
cout << "--prefix-reg-from-id 0,1 - Использовать в качестве регистра sensor ID" << endl;
cout << "--prefix-filter-field name - Считывать список опрашиваемых датчиков, только у которых есть поле field" << endl;
cout << "--prefix-filter-value val - Считывать список опрашиваемых датчиков, только у которых field=value" << endl;
cout << "--prefix-statistic-sec sec - Выводить статистику опроса каждые sec секунд" << endl;
cout << "--prefix-sm-ready-timeout - время на ожидание старта SM" << endl;
}
// -----------------------------------------------------------------------------
MBExchange::~MBExchange()
{
delete shm;
}
// -----------------------------------------------------------------------------
void MBExchange::waitSMReady()
{
// waiting for SM is ready...
int ready_timeout = conf->getArgInt("--" + prefix +"-sm-ready-timeout","15000");
if( ready_timeout == 0 )
ready_timeout = 15000;
else if( ready_timeout < 0 )
ready_timeout = UniSetTimer::WaitUpTime;
if( !shm->waitSMready(ready_timeout, 50) )
{
ostringstream err;
err << myname << "(waitSMReady): failed waiting SharedMemory " << ready_timeout << " msec";
dlog[Debug::CRIT] << err.str() << endl;
throw SystemError(err.str());
}
}
// -----------------------------------------------------------------------------
void MBExchange::step()
{
if( !checkProcActive() )
return;
if( sidHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
shm->localSaveValue(aitHeartBeat,sidHeartBeat,maxHeartBeat,getId());
ptHeartBeat.reset();
}
catch(Exception& ex)
{
dlog[Debug::CRIT] << myname
<< "(step): (hb) " << ex << std::endl;
}
}
}
// -----------------------------------------------------------------------------
bool MBExchange::checkProcActive()
{
uniset_mutex_lock l(actMutex, 300);
return activated;
}
// -----------------------------------------------------------------------------
void MBExchange::setProcActive( bool st )
{
uniset_mutex_lock l(actMutex, 400);
activated = st;
}
// -----------------------------------------------------------------------------
void MBExchange::sigterm( int signo )
{
dlog[Debug::WARN] << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
setProcActive(false);
UniSetObject_LT::sigterm(signo);
}
// ------------------------------------------------------------------------------------------
void MBExchange::readConfiguration()
{
// readconf_ok = false;
xmlNode* root = conf->getXMLSensorsSection();
if(!root)
{
ostringstream err;
err << myname << "(readConfiguration): не нашли корневого раздела <sensors>";
throw SystemError(err.str());
}
UniXML_iterator it(root);
if( !it.goChildren() )
{
dlog[Debug::CRIT] << myname << "(readConfiguration): раздел <sensors> не содержит секций ?!!\n";
return;
}
for( ;it.getCurrent(); it.goNext() )
{
if( UniSetTypes::check_filter(it,s_field,s_fvalue) )
initItem(it);
}
// readconf_ok = true;
}
// ------------------------------------------------------------------------------------------
bool MBExchange::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
{
if( UniSetTypes::check_filter(it,s_field,s_fvalue) )
initItem(it);
return true;
}
// ------------------------------------------------------------------------------------------
MBExchange::DeviceType MBExchange::getDeviceType( const std::string dtype )
{
if( dtype.empty() )
return dtUnknown;
if( dtype == "mtr" || dtype == "MTR" )
return dtMTR;
if( dtype == "rtu" || dtype == "RTU" )
return dtRTU;
return dtUnknown;
}
// ------------------------------------------------------------------------------------------
void MBExchange::initIterators()
{
shm->initAIterator(aitHeartBeat);
shm->initAIterator(aitExchangeMode);
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
shm->initDIterator(d->resp_dit);
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
for( PList::iterator it2=it->second->slst.begin();it2!=it->second->slst.end(); ++it2 )
{
shm->initDIterator(it2->dit);
shm->initAIterator(it2->ait);
}
}
}
}
// -----------------------------------------------------------------------------
bool MBExchange::checkUpdateSM( bool wrFunc )
{
if( wrFunc && exchangeMode == emReadOnly )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "(checkUpdateSM):"
<< " skip... mode='emReadOnly' " << endl;
return false;
}
if( !wrFunc && exchangeMode == emWriteOnly )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "(checkUpdateSM):"
<< " skip... mode='emWriteOnly' " << endl;
return false;
}
if( wrFunc && exchangeMode == emSkipSaveToSM )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "(checkUpdateSM):"
<< " skip... mode='emSkipSaveToSM' " << endl;
return false;
}
return true;
}
// -----------------------------------------------------------------------------
bool MBExchange::checkPoll( bool wrFunc )
{
if( exchangeMode == emWriteOnly && !wrFunc )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(checkPoll): skip.. mode='emWriteOnly'" << endl;
return false;
}
if( exchangeMode == emReadOnly && wrFunc )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(checkPoll): skip.. poll mode='emReadOnly'" << endl;
return false;
}
return true;
}
// -----------------------------------------------------------------------------
MBExchange::RegID MBExchange::genRegID( const ModbusRTU::ModbusData mbreg, const int fn )
{
// формула для вычисления ID
// требования:
// 1. ID > диапазона возможных регистров
// 2. одинаковые регистры, но разные функции должны давать разный ID
// 3. регистры идущие подряд, должна давать ID идущие тоже подряд
// Вообще диапазоны:
// mbreg: 0..65535
// fn: 0...255
int max = numeric_limits<ModbusRTU::ModbusData>::max(); // по идее 65535
int fn_max = numeric_limits<ModbusRTU::ModbusByte>::max(); // по идее 255
// fn необходимо привести к диапазону 0..max
return max + mbreg + max + UniSetTypes::lcalibrate(fn,0,fn_max,0,max,false);
}
// ------------------------------------------------------------------------------------------
void MBExchange::printMap( MBExchange::RTUDeviceMap& m )
{
cout << "devices: " << endl;
for( MBExchange::RTUDeviceMap::iterator it=m.begin(); it!=m.end(); ++it )
{
cout << " " << *(it->second) << endl;
}
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBExchange::RTUDeviceMap& m )
{
os << "devices: " << endl;
for( MBExchange::RTUDeviceMap::iterator it=m.begin(); it!=m.end(); ++it )
{
os << " " << *(it->second) << endl;
}
return os;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBExchange::RTUDevice& d )
{
os << "addr=" << ModbusRTU::addr2str(d.mbaddr)
<< " type=" << d.dtype
<< " respond_id=" << d.resp_id
<< " respond_timeout=" << d.resp_ptTimeout.getInterval()
<< " respond_state=" << d.resp_state
<< " respond_invert=" << d.resp_invert
<< endl;
os << " regs: " << endl;
for( MBExchange::RegMap::iterator it=d.regmap.begin(); it!=d.regmap.end(); ++it )
os << " " << *(it->second) << endl;
return os;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBExchange::RegInfo& r )
{
os << " id=" << r.id
<< " mbreg=" << ModbusRTU::dat2str(r.mbreg)
<< " mbfunc=" << r.mbfunc
<< " q_num=" << r.q_num
<< " q_count=" << r.q_count
<< " value=" << ModbusRTU::dat2str(r.mbval) << "(" << (int)r.mbval << ")"
<< " mtrType=" << MTR::type2str(r.mtrType)
<< endl;
for( MBExchange::PList::iterator it=r.slst.begin(); it!=r.slst.end(); ++it )
os << " " << (*it) << endl;
return os;
}
// -----------------------------------------------------------------------------
void MBExchange::rtuQueryOptimization( RTUDeviceMap& m )
{
if( noQueryOptimization )
return;
dlog[Debug::INFO] << myname << "(rtuQueryOptimization): optimization..." << endl;
for( MBExchange::RTUDeviceMap::iterator it1=m.begin(); it1!=m.end(); ++it1 )
{
RTUDevice* d(it1->second);
// Вообще в map они уже лежат в нужном порядке, т.е. функция genRegID() гарантирует
// что регистры идущие подряд с одниковой функцией чтения/записи получат подряд идущие ID.
// так что оптимтизация это просто нахождение мест где id идут не подряд...
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
MBExchange::RegMap::iterator beg = it;
RegID id = it->second->id; // или собственно it->first
beg->second->q_num = 1;
beg->second->q_count = 1;
it++;
for( ;it!=d->regmap.end(); ++it )
{
if( (it->second->id - id) > 1 )
{
it--; // раз это регистр уже следующий, то надо вернуть на шаг обратно..
break;
}
beg->second->q_count++;
if( beg->second->q_count >= ModbusRTU::MAXDATALEN )
break;
id = it->second->id;
it->second->q_num = beg->second->q_count;
it->second->q_count = 0;
}
// check correct function...
if( beg->second->q_count>1 && beg->second->mbfunc==ModbusRTU::fnWriteOutputSingleRegister )
{
dlog[Debug::WARN] << myname << "(rtuQueryOptimization): "
<< " optimization change func=" << ModbusRTU::fnWriteOutputSingleRegister
<< " <--> func=" << ModbusRTU::fnWriteOutputRegisters
<< " for mbaddr=" << ModbusRTU::addr2str(d->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(beg->second->mbreg);
beg->second->mbfunc = ModbusRTU::fnWriteOutputRegisters;
}
else if( beg->second->q_count>1 && beg->second->mbfunc==ModbusRTU::fnForceSingleCoil )
{
dlog[Debug::WARN] << myname << "(rtuQueryOptimization): "
<< " optimization change func=" << ModbusRTU::fnForceSingleCoil
<< " <--> func=" << ModbusRTU::fnForceMultipleCoils
<< " for mbaddr=" << ModbusRTU::addr2str(d->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(beg->second->mbreg);
beg->second->mbfunc = ModbusRTU::fnForceMultipleCoils;
}
if( it==d->regmap.end() )
break;
}
}
}
// -----------------------------------------------------------------------------
//std::ostream& operator<<( std::ostream& os, MBExchange::PList& lst )
std::ostream& MBExchange::print_plist( std::ostream& os, MBExchange::PList& lst )
{
os << "[ ";
for( MBExchange::PList::const_iterator it=lst.begin(); it!=lst.end(); ++it )
os << "(" << it->si.id << ")" << conf->oind->getBaseName(conf->oind->getMapName(it->si.id)) << " ";
os << "]";
return os;
}
// -----------------------------------------------------------------------------
void MBExchange::firstInitRegisters()
{
// если все вернут TRUE, значит OK.
allInitOK = true;
for( InitList::iterator it=initRegList.begin(); it!=initRegList.end(); ++it )
{
try
{
it->initOK = preInitRead(it);
allInitOK = it->initOK;
}
catch( ModbusRTU::mbException& ex )
{
allInitOK = false;
if( dlog.debugging(Debug::LEVEL3) )
{
dlog[Debug::LEVEL3] << myname << "(preInitRead): FAILED ask addr=" << ModbusRTU::addr2str(it->dev->mbaddr)
<< " reg=" << ModbusRTU::dat2str(it->mbreg)
<< " err: " << ex << endl;
}
if( !it->dev->ask_every_reg )
break;
}
}
}
// -----------------------------------------------------------------------------
bool MBExchange::preInitRead( InitList::iterator& p )
{
if( p->initOK )
return true;
RTUDevice* dev = p->dev;
int q_count = p->p.rnum;
if( dlog.debugging(Debug::LEVEL3) )
{
dlog[Debug::LEVEL3] << myname << "(preInitRead): poll "
<< " mbaddr=" << ModbusRTU::addr2str(dev->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " mbfunc=" << p->mbfunc
<< " q_count=" << q_count
<< endl;
if( q_count > ModbusRTU::MAXDATALEN )
{
dlog[Debug::LEVEL3] << myname << "(preInitRead): count(" << q_count
<< ") > MAXDATALEN(" << ModbusRTU::MAXDATALEN
<< " ..ignore..."
<< endl;
}
}
switch( p->mbfunc )
{
case ModbusRTU::fnReadOutputRegisters:
{
ModbusRTU::ReadOutputRetMessage ret = mb->read03(dev->mbaddr,p->mbreg,q_count);
p->initOK = initSMValue(ret.data, ret.count,&(p->p));
}
break;
case ModbusRTU::fnReadInputRegisters:
{
ModbusRTU::ReadInputRetMessage ret1 = mb->read04(dev->mbaddr,p->mbreg,q_count);
p->initOK = initSMValue(ret1.data,ret1.count, &(p->p));
}
break;
case ModbusRTU::fnReadInputStatus:
{
ModbusRTU::ReadInputStatusRetMessage ret = mb->read02(dev->mbaddr,p->mbreg,q_count);
ModbusRTU::ModbusData* dat = new ModbusRTU::ModbusData[q_count];
int m=0;
for( int i=0; i<ret.bcnt; i++ )
{
ModbusRTU::DataBits b(ret.data[i]);
for( int k=0;k<ModbusRTU::BitsPerByte && m<q_count; k++,m++ )
dat[m] = b[k];
}
p->initOK = initSMValue(dat,q_count, &(p->p));
delete[] dat;
}
break;
case ModbusRTU::fnReadCoilStatus:
{
ModbusRTU::ReadCoilRetMessage ret = mb->read01(dev->mbaddr,p->mbreg,q_count);
ModbusRTU::ModbusData* dat = new ModbusRTU::ModbusData[q_count];
int m = 0;
for( int i=0; i<ret.bcnt; i++ )
{
ModbusRTU::DataBits b(ret.data[i]);
for( int k=0;k<ModbusRTU::BitsPerByte && m<q_count; k++,m++ )
dat[m] = b[k];
}
p->initOK = initSMValue(dat,q_count, &(p->p));
delete[] dat;
}
break;
default:
p->initOK = false;
break;
}
if( p->initOK )
{
bool f_out = force_out;
// выставляем флаг принудительного обновления
force_out = true;
p->ri->mb_initOK = true;
p->ri->sm_initOK = false;
updateRTU(p->ri->rit);
force_out = f_out;
}
return p->initOK;
}
// -----------------------------------------------------------------------------
bool MBExchange::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p )
{
using namespace ModbusRTU;
try
{
if( p->vType == VTypes::vtUnknown )
{
ModbusRTU::DataBits16 b(data[0]);
if( p->nbit >= 0 )
{
bool set = b[p->nbit];
IOBase::processingAsDI( p, set, shm, force );
return true;
}
if( p->rnum <= 1 )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
IOBase::processingAsDI( p, data[0], shm, force );
}
else
IOBase::processingAsAI( p, (signed short)(data[0]), shm, force );
return true;
}
dlog[Debug::CRIT] << myname << "(initSMValue): IGNORE item: rnum=" << p->rnum
<< " > 1 ?!! for id=" << p->si.id << endl;
return false;
}
else if( p->vType == VTypes::vtSigned )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
IOBase::processingAsDI( p, data[0], shm, force );
}
else
IOBase::processingAsAI( p, (signed short)(data[0]), shm, force );
return true;
}
else if( p->vType == VTypes::vtUnsigned )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
IOBase::processingAsDI( p, data[0], shm, force );
}
else
IOBase::processingAsAI( p, (unsigned short)data[0], shm, force );
return true;
}
else if( p->vType == VTypes::vtByte )
{
if( p->nbyte <= 0 || p->nbyte > VTypes::Byte::bsize )
{
dlog[Debug::CRIT] << myname << "(initSMValue): IGNORE item: sid=" << ModbusRTU::dat2str(p->si.id)
<< " vtype=" << p->vType << " but nbyte=" << p->nbyte << endl;
return false;
}
VTypes::Byte b(data[0]);
IOBase::processingAsAI( p, b.raw.b[p->nbyte-1], shm, force );
return true;
}
else if( p->vType == VTypes::vtF2 )
{
VTypes::F2 f(data,VTypes::F2::wsize());
IOBase::processingFasAI( p, (float)f, shm, force );
}
else if( p->vType == VTypes::vtF4 )
{
VTypes::F4 f(data,VTypes::F4::wsize());
IOBase::processingFasAI( p, (float)f, shm, force );
}
else if( p->vType == VTypes::vtI2 )
{
VTypes::I2 i2(data,VTypes::I2::wsize());
IOBase::processingAsAI( p, (int)i2, shm, force );
}
else if( p->vType == VTypes::vtU2 )
{
VTypes::U2 u2(data,VTypes::U2::wsize());
IOBase::processingAsAI( p, (unsigned int)u2, shm, force );
}
return true;
}
catch(IOController_i::NameNotFound &ex)
{
dlog[Debug::LEVEL3] << myname << "(initSMValue):(NameNotFound) " << ex.err << endl;
}
catch(IOController_i::IOBadParam& ex )
{
dlog[Debug::LEVEL3] << myname << "(initSMValue):(IOBadParam) " << ex.err << endl;
}
catch(IONotifyController_i::BadRange )
{
dlog[Debug::LEVEL3] << myname << "(initSMValue): (BadRange)..." << endl;
}
catch( Exception& ex )
{
dlog[Debug::LEVEL3] << myname << "(initSMValue): " << ex << endl;
}
catch(CORBA::SystemException& ex)
{
dlog[Debug::LEVEL3] << myname << "(initSMValue): CORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch(...)
{
dlog[Debug::LEVEL3] << myname << "(initSMValue): catch ..." << endl;
}
return false;
}
// -----------------------------------------------------------------------------
bool MBExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
{
RegInfo* p(it->second);
if( dlog.debugging(Debug::LEVEL3) )
{
dlog[Debug::LEVEL3] << myname << "(pollRTU): poll "
<< " mbaddr=" << ModbusRTU::addr2str(dev->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " mbfunc=" << p->mbfunc
<< " q_count=" << p->q_count
<< " mb_initOK=" << p->mb_initOK
<< " sm_initOK=" << p->sm_initOK
<< " mbval=" << p->mbval
<< endl;
if( p->q_count > ModbusRTU::MAXDATALEN )
{
dlog[Debug::LEVEL3] << myname << "(pollRTU): count(" << p->q_count
<< ") > MAXDATALEN(" << ModbusRTU::MAXDATALEN
<< " ..ignore..."
<< endl;
}
}
if( !checkPoll(ModbusRTU::isWriteFunction(p->mbfunc)) )
return true;
if( p->q_count == 0 )
{
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(pollRTU): q_count=0 for mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE register..." << endl;
return false;
}
switch( p->mbfunc )
{
case ModbusRTU::fnReadInputRegisters:
{
ModbusRTU::ReadInputRetMessage ret = mb->read04(dev->mbaddr,p->mbreg,p->q_count);
for( int i=0; i<p->q_count; i++,it++ )
it->second->mbval = ret.data[i];
it--;
}
break;
case ModbusRTU::fnReadOutputRegisters:
{
ModbusRTU::ReadOutputRetMessage ret = mb->read03(dev->mbaddr, p->mbreg,p->q_count);
for( int i=0; i<p->q_count; i++,it++ )
it->second->mbval = ret.data[i];
it--;
}
break;
case ModbusRTU::fnReadInputStatus:
{
ModbusRTU::ReadInputStatusRetMessage ret = mb->read02(dev->mbaddr,p->mbreg,p->q_count);
int m=0;
for( int i=0; i<ret.bcnt; i++ )
{
ModbusRTU::DataBits b(ret.data[i]);
for( int k=0;k<ModbusRTU::BitsPerByte && m<p->q_count; k++,it++,m++ )
it->second->mbval = b[k];
}
it--;
}
break;
case ModbusRTU::fnReadCoilStatus:
{
ModbusRTU::ReadCoilRetMessage ret = mb->read01(dev->mbaddr,p->mbreg,p->q_count);
int m = 0;
for( int i=0; i<ret.bcnt; i++ )
{
ModbusRTU::DataBits b(ret.data[i]);
for( int k=0;k<ModbusRTU::BitsPerByte && m<p->q_count; k++,it++,m++ )
it->second->mbval = b[k] ? 1 : 0;
}
it--;
}
break;
case ModbusRTU::fnWriteOutputSingleRegister:
{
if( p->q_count != 1 )
{
dlog[Debug::CRIT] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE WRITE SINGLE REGISTER (0x06) q_count=" << p->q_count << " ..." << endl;
return false;
}
if( !p->sm_initOK )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " slist=" << (*p)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
// cerr << "**** mbreg=" << ModbusRTU::dat2str(p->mbreg) << " val=" << ModbusRTU::dat2str(p->mbval) << endl;
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(dev->mbaddr,p->mbreg,p->mbval);
}
break;
case ModbusRTU::fnWriteOutputRegisters:
{
if( !p->sm_initOK )
{
// может быть такая ситуация, что
// некоторые регистры уже инициализированы, а другие ещё нет
// при этом после оптимизации они попадают в один запрос
// поэтому здесь сделано так:
// если q_num > 1, значит этот регистр относится к предыдущему запросу
// и его просто надо пропустить..
if( p->q_num > 1 )
return true;
// смещаем итератор, если данный запрос содержит много регистров
// if( q->count > 1 )
// {
// for( int i=0; i<p->q_count; i++ )
// it++;
// return true;
// }
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
ModbusRTU::WriteOutputMessage msg(dev->mbaddr,p->mbreg);
for( int i=0; i<p->q_count; i++,it++ )
msg.addData(it->second->mbval);
it--;
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
}
break;
case ModbusRTU::fnForceSingleCoil:
{
if( p->q_count != 1 )
{
dlog[Debug::CRIT] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE FORCE SINGLE COIL (0x05) q_count=" << p->q_count << " ..." << endl;
return false;
}
if( !p->sm_initOK )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
// cerr << "****(coil) mbreg=" << ModbusRTU::dat2str(p->mbreg) << " val=" << ModbusRTU::dat2str(p->mbval) << endl;
ModbusRTU::ForceSingleCoilRetMessage ret = mb->write05(dev->mbaddr,p->mbreg,p->mbval);
}
break;
case ModbusRTU::fnForceMultipleCoils:
{
if( !p->sm_initOK )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
ModbusRTU::ForceCoilsMessage msg(dev->mbaddr,p->mbreg);
for( int i=0; i<p->q_count; i++,it++ )
msg.addBit( (it->second->mbval ? true : false) );
it--;
// cerr << "*********** (write multiple): " << msg << endl;
ModbusRTU::ForceCoilsRetMessage ret = mb->write0F(msg);
}
break;
default:
{
if( dlog.debugging(Debug::WARN) )
dlog[Debug::WARN] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE mfunc=" << (int)p->mbfunc << " ..." << endl;
return false;
}
break;
}
return true;
}
// -----------------------------------------------------------------------------
void MBExchange::updateSM()
{
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
// обновление датчиков связи происходит в другом потоке
// чтобы не зависеть от TCP таймаутов
// см. updateRespondSensors()
// update values...
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
try
{
if( d->dtype == dtRTU )
updateRTU(it);
else if( d->dtype == dtMTR )
updateMTR(it);
}
catch(IOController_i::NameNotFound &ex)
{
dlog[Debug::LEVEL3] << myname << "(updateSM):(NameNotFound) " << ex.err << endl;
}
catch(IOController_i::IOBadParam& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateSM):(IOBadParam) " << ex.err << endl;
}
catch(IONotifyController_i::BadRange )
{
dlog[Debug::LEVEL3] << myname << "(updateSM): (BadRange)..." << endl;
}
catch( Exception& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateSM): " << ex << endl;
}
catch(CORBA::SystemException& ex)
{
dlog[Debug::LEVEL3] << myname << "(updateSM): CORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch(...)
{
dlog[Debug::LEVEL3] << myname << "(updateSM): catch ..." << endl;
}
if( it==d->regmap.end() )
break;
}
}
}
// -----------------------------------------------------------------------------
void MBExchange::updateRTU( RegMap::iterator& rit )
{
RegInfo* r(rit->second);
for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it )
updateRSProperty( &(*it),false );
}
// -----------------------------------------------------------------------------
void MBExchange::updateRSProperty( RSProperty* p, bool write_only )
{
using namespace ModbusRTU;
RegInfo* r(p->reg->rit->second);
bool save = isWriteFunction( r->mbfunc );
if( !save && write_only )
return;
if( !checkUpdateSM(save) )
return;
// если требуется инициализация и она ещё не произведена,
// то игнорируем
if( save && !r->mb_initOK )
return;
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "updateP: sid=" << p->si.id
<< " mbval=" << r->mbval
<< " vtype=" << p->vType
<< " rnum=" << p->rnum
<< " nbit=" << p->nbit
<< " save=" << save
<< " ioype=" << p->stype
<< " mb_initOK=" << r->mb_initOK
<< " sm_initOK=" << r->sm_initOK
<< endl;
try
{
if( p->vType == VTypes::vtUnknown )
{
ModbusRTU::DataBits16 b(r->mbval);
if( p->nbit >= 0 )
{
if( save )
{
if( r->mb_initOK )
{
bool set = IOBase::processingAsDO( p, shm, force_out );
b.set(p->nbit,set);
r->mbval = b.mdata();
r->sm_initOK = true;
}
}
else
{
bool set = b[p->nbit];
IOBase::processingAsDI( p, set, shm, force );
}
return;
}
if( p->rnum <= 1 )
{
if( save )
{
if( r->mb_initOK )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
r->mbval = IOBase::processingAsDO( p, shm, force_out );
}
else
r->mbval = IOBase::processingAsAO( p, shm, force_out );
r->sm_initOK = true;
}
}
else
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
IOBase::processingAsDI( p, r->mbval, shm, force );
}
else
IOBase::processingAsAI( p, (signed short)(r->mbval), shm, force );
}
return;
}
dlog[Debug::CRIT] << myname << "(updateRSProperty): IGNORE item: rnum=" << p->rnum
<< " > 1 ?!! for id=" << p->si.id << endl;
return;
}
else if( p->vType == VTypes::vtSigned )
{
if( save )
{
if( r->mb_initOK )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
r->mbval = (signed short)IOBase::processingAsDO( p, shm, force_out );
}
else
r->mbval = (signed short)IOBase::processingAsAO( p, shm, force_out );
r->sm_initOK = true;
}
}
else
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
IOBase::processingAsDI( p, r->mbval, shm, force );
}
else
{
IOBase::processingAsAI( p, (signed short)(r->mbval), shm, force );
}
}
return;
}
else if( p->vType == VTypes::vtUnsigned )
{
if( save )
{
if( r->mb_initOK )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
r->mbval = (unsigned short)IOBase::processingAsDO( p, shm, force_out );
}
else
r->mbval = (unsigned short)IOBase::processingAsAO( p, shm, force_out );
r->sm_initOK = true;
}
}
else
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
{
IOBase::processingAsDI( p, r->mbval, shm, force );
}
else
{
IOBase::processingAsAI( p, (unsigned short)r->mbval, shm, force );
}
}
return;
}
else if( p->vType == VTypes::vtByte )
{
if( p->nbyte <= 0 || p->nbyte > VTypes::Byte::bsize )
{
dlog[Debug::CRIT] << myname << "(updateRSProperty): IGNORE item: reg=" << ModbusRTU::dat2str(r->mbreg)
<< " vtype=" << p->vType << " but nbyte=" << p->nbyte << endl;
return;
}
if( save && r->sm_initOK )
{
if( r->mb_initOK )
{
long v = IOBase::processingAsAO( p, shm, force_out );
VTypes::Byte b(r->mbval);
b.raw.b[p->nbyte-1] = v;
r->mbval = b.raw.w;
r->sm_initOK = true;
}
}
else
{
VTypes::Byte b(r->mbval);
IOBase::processingAsAI( p, b.raw.b[p->nbyte-1], shm, force );
}
return;
}
else if( p->vType == VTypes::vtF2 )
{
RegMap::iterator i(p->reg->rit);
if( save )
{
if( r->mb_initOK )
{
float f = IOBase::processingFasAO( p, shm, force_out );
VTypes::F2 f2(f);
for( int k=0; k<VTypes::F2::wsize(); k++, i++ )
i->second->mbval = f2.raw.v[k];
r->sm_initOK = true;
}
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[VTypes::F2::wsize()];
for( int k=0; k<VTypes::F2::wsize(); k++, i++ )
data[k] = i->second->mbval;
VTypes::F2 f(data,VTypes::F2::wsize());
delete[] data;
IOBase::processingFasAI( p, (float)f, shm, force );
}
}
else if( p->vType == VTypes::vtF4 )
{
RegMap::iterator i(p->reg->rit);
if( save )
{
if( r->mb_initOK )
{
float f = IOBase::processingFasAO( p, shm, force_out );
VTypes::F4 f4(f);
for( int k=0; k<VTypes::F4::wsize(); k++, i++ )
i->second->mbval = f4.raw.v[k];
}
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[VTypes::F4::wsize()];
for( int k=0; k<VTypes::F4::wsize(); k++, i++ )
data[k] = i->second->mbval;
VTypes::F4 f(data,VTypes::F4::wsize());
delete[] data;
IOBase::processingFasAI( p, (float)f, shm, force );
}
}
else if( p->vType == VTypes::vtI2 )
{
RegMap::iterator i(p->reg->rit);
if( save )
{
if( r->mb_initOK )
{
long v = IOBase::processingAsAO( p, shm, force_out );
VTypes::I2 i2(v);
for( int k=0; k<VTypes::I2::wsize(); k++, i++ )
i->second->mbval = i2.raw.v[k];
r->sm_initOK = true;
}
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[VTypes::I2::wsize()];
for( int k=0; k<VTypes::I2::wsize(); k++, i++ )
data[k] = i->second->mbval;
VTypes::I2 i2(data,VTypes::I2::wsize());
delete[] data;
IOBase::processingAsAI( p, (int)i2, shm, force );
}
}
else if( p->vType == VTypes::vtU2 )
{
RegMap::iterator i(p->reg->rit);
if( save )
{
if( r->mb_initOK )
{
long v = IOBase::processingAsAO( p, shm, force_out );
VTypes::U2 u2(v);
for( int k=0; k<VTypes::U2::wsize(); k++, i++ )
i->second->mbval = u2.raw.v[k];
r->sm_initOK = true;
}
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[VTypes::U2::wsize()];
for( int k=0; k<VTypes::U2::wsize(); k++, i++ )
data[k] = i->second->mbval;
VTypes::U2 u2(data,VTypes::U2::wsize());
delete[] data;
IOBase::processingAsAI( p, (unsigned int)u2, shm, force );
}
}
return;
}
catch(IOController_i::NameNotFound &ex)
{
dlog[Debug::LEVEL3] << myname << "(updateRSProperty):(NameNotFound) " << ex.err << endl;
}
catch(IOController_i::IOBadParam& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateRSProperty):(IOBadParam) " << ex.err << endl;
}
catch(IONotifyController_i::BadRange )
{
dlog[Debug::LEVEL3] << myname << "(updateRSProperty): (BadRange)..." << endl;
}
catch( Exception& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateRSProperty): " << ex << endl;
}
catch(CORBA::SystemException& ex)
{
dlog[Debug::LEVEL3] << myname << "(updateRSProperty): CORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch(...)
{
dlog[Debug::LEVEL3] << myname << "(updateRSProperty): catch ..." << endl;
}
// Если SM стала (или была) недоступна
// то флаг инициализации надо сбросить
r->sm_initOK = false;
}
// -----------------------------------------------------------------------------
void MBExchange::updateMTR( RegMap::iterator& rit )
{
RegInfo* r(rit->second);
using namespace ModbusRTU;
bool save = isWriteFunction( r->mbfunc );
if( save && exchangeMode == emReadOnly )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateMTR):"
<< " skip... mode=emReadOnly " << endl;
return;
}
if( !save && exchangeMode == emWriteOnly )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateMTR):"
<< " skip... mode=emWriteOnly " << endl;
return;
}
if( save && exchangeMode == emSkipSaveToSM )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(updateMTR):"
<< " skip... mode=emSkipSaveToSM " << endl;
return;
}
{
for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it )
{
try
{
if( r->mtrType == MTR::mtT1 )
{
if( save )
r->mbval = IOBase::processingAsAO( &(*it), shm, force_out );
else
{
MTR::T1 t(r->mbval);
IOBase::processingAsAI( &(*it), t.val, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT2 )
{
if( save )
{
MTR::T2 t(IOBase::processingAsAO( &(*it), shm, force_out ));
r->mbval = t.val;
}
else
{
MTR::T2 t(r->mbval);
IOBase::processingAsAI( &(*it), t.val, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT3 )
{
RegMap::iterator i(rit);
if( save )
{
MTR::T3 t(IOBase::processingAsAO( &(*it), shm, force_out ));
for( int k=0; k<MTR::T3::wsize(); k++, i++ )
i->second->mbval = t.raw.v[k];
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[MTR::T3::wsize()];
for( int k=0; k<MTR::T3::wsize(); k++, i++ )
data[k] = i->second->mbval;
MTR::T3 t(data,MTR::T3::wsize());
delete[] data;
IOBase::processingAsAI( &(*it), (long)t, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT4 )
{
if( save )
dlog[Debug::WARN] << myname << "(updateMTR): write (T4) reg(" << dat2str(r->mbreg) << ") to MTR NOT YET!!!" << endl;
else
{
MTR::T4 t(r->mbval);
IOBase::processingAsAI( &(*it), uni_atoi(t.sval), shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT5 )
{
RegMap::iterator i(rit);
if( save )
{
MTR::T5 t(IOBase::processingAsAO( &(*it), shm, force_out ));
for( int k=0; k<MTR::T5::wsize(); k++, i++ )
i->second->mbval = t.raw.v[k];
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[MTR::T5::wsize()];
for( int k=0; k<MTR::T5::wsize(); k++, i++ )
data[k] = i->second->mbval;
MTR::T5 t(data,MTR::T5::wsize());
delete[] data;
IOBase::processingFasAI( &(*it), (float)t.val, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT6 )
{
RegMap::iterator i(rit);
if( save )
{
MTR::T6 t(IOBase::processingAsAO( &(*it), shm, force_out ));
for( int k=0; k<MTR::T6::wsize(); k++, i++ )
i->second->mbval = t.raw.v[k];
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[MTR::T6::wsize()];
for( int k=0; k<MTR::T6::wsize(); k++, i++ )
data[k] = i->second->mbval;
MTR::T6 t(data,MTR::T6::wsize());
delete[] data;
IOBase::processingFasAI( &(*it), (float)t.val, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT7 )
{
RegMap::iterator i(rit);
if( save )
{
MTR::T7 t(IOBase::processingAsAO( &(*it), shm, force_out ));
for( int k=0; k<MTR::T7::wsize(); k++, i++ )
i->second->mbval = t.raw.v[k];
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[MTR::T7::wsize()];
for( int k=0; k<MTR::T7::wsize(); k++, i++ )
data[k] = i->second->mbval;
MTR::T7 t(data,MTR::T7::wsize());
delete[] data;
IOBase::processingFasAI( &(*it), (float)t.val, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT16 )
{
if( save )
{
MTR::T16 t(IOBase::processingFasAO( &(*it), shm, force_out ));
r->mbval = t.val;
}
else
{
MTR::T16 t(r->mbval);
IOBase::processingFasAI( &(*it), t.fval, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtT17 )
{
if( save )
{
MTR::T17 t(IOBase::processingFasAO( &(*it), shm, force_out ));
r->mbval = t.val;
}
else
{
MTR::T17 t(r->mbval);
IOBase::processingFasAI( &(*it), t.fval, shm, force );
}
continue;
}
if( r->mtrType == MTR::mtF1 )
{
RegMap::iterator i(rit);
if( save )
{
float f = IOBase::processingFasAO( &(*it), shm, force_out );
MTR::F1 f1(f);
for( int k=0; k<MTR::F1::wsize(); k++, i++ )
i->second->mbval = f1.raw.v[k];
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[MTR::F1::wsize()];
for( int k=0; k<MTR::F1::wsize(); k++, i++ )
data[k] = i->second->mbval;
MTR::F1 t(data,MTR::F1::wsize());
delete[] data;
IOBase::processingFasAI( &(*it), (float)t, shm, force );
}
continue;
}
}
catch(IOController_i::NameNotFound &ex)
{
dlog[Debug::LEVEL3] << myname << "(updateMTR):(NameNotFound) " << ex.err << endl;
}
catch(IOController_i::IOBadParam& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateMTR):(IOBadParam) " << ex.err << endl;
}
catch(IONotifyController_i::BadRange )
{
dlog[Debug::LEVEL3] << myname << "(updateMTR): (BadRange)..." << endl;
}
catch( Exception& ex )
{
dlog[Debug::LEVEL3] << myname << "(updateMTR): " << ex << endl;
}
catch(CORBA::SystemException& ex)
{
dlog[Debug::LEVEL3] << myname << "(updateMTR): CORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch(...)
{
dlog[Debug::LEVEL3] << myname << "(updateMTR): catch ..." << endl;
}
}
}
}
// -----------------------------------------------------------------------------
MBExchange::RTUDevice* MBExchange::addDev( RTUDeviceMap& mp, ModbusRTU::ModbusAddr a, UniXML_iterator& xmlit )
{
RTUDeviceMap::iterator it = mp.find(a);
if( it != mp.end() )
{
DeviceType dtype = getDeviceType(xmlit.getProp(prop_prefix + "mbtype"));
if( it->second->dtype != dtype )
{
dlog[Debug::CRIT] << myname << "(addDev): OTHER mbtype=" << dtype << " for " << xmlit.getProp("name")
<< ". Already used devtype=" << it->second->dtype
<< " for mbaddr=" << ModbusRTU::addr2str(it->second->mbaddr)
<< endl;
return 0;
}
dlog[Debug::INFO] << myname << "(addDev): device for addr=" << ModbusRTU::addr2str(a)
<< " already added. Ignore device params for " << xmlit.getProp("name") << " ..." << endl;
return it->second;
}
MBExchange::RTUDevice* d = new MBExchange::RTUDevice();
d->mbaddr = a;
if( !initRTUDevice(d,xmlit) )
{
delete d;
return 0;
}
mp.insert(RTUDeviceMap::value_type(a,d));
return d;
}
// ------------------------------------------------------------------------------------------
MBExchange::RegInfo* MBExchange::addReg( RegMap& mp, RegID id, ModbusRTU::ModbusData r,
UniXML_iterator& xmlit, MBExchange::RTUDevice* dev,
MBExchange::RegInfo* rcopy )
{
RegMap::iterator it = mp.find(id);
if( it != mp.end() )
{
if( !it->second->dev )
{
dlog[Debug::CRIT] << myname << "(addReg): for " << xmlit.getProp("name")
<< " dev=0!!!! " << endl;
return 0;
}
if( it->second->dev->dtype != dev->dtype )
{
dlog[Debug::CRIT] << myname << "(addReg): OTHER mbtype=" << dev->dtype << " for " << xmlit.getProp("name")
<< ". Already used devtype=" << it->second->dev->dtype << " for " << it->second->dev << endl;
return 0;
}
if( dlog.debugging(Debug::INFO) )
{
dlog[Debug::INFO] << myname << "(addReg): reg=" << ModbusRTU::dat2str(r)
<< "(id=" << id << ")"
<< " already added for " << (*it->second)
<< " Ignore register params for " << xmlit.getProp("name") << " ..." << endl;
}
it->second->rit = it;
return it->second;
}
MBExchange::RegInfo* ri;
if( rcopy )
{
ri = new MBExchange::RegInfo(*rcopy);
ri->slst.clear();
ri->mbreg = r;
}
else
{
ri = new MBExchange::RegInfo();
if( !initRegInfo(ri,xmlit,dev) )
{
delete ri;
return 0;
}
ri->mbreg = r;
}
ri->id = id;
mp.insert(RegMap::value_type(id,ri));
ri->rit = mp.find(id);
return ri;
}
// ------------------------------------------------------------------------------------------
MBExchange::RSProperty* MBExchange::addProp( PList& plist, RSProperty& p )
{
for( PList::iterator it=plist.begin(); it!=plist.end(); ++it )
{
if( it->si.id == p.si.id && it->si.node == p.si.node )
return &(*it);
}
plist.push_back(p);
PList::iterator it = plist.end();
it--;
return &(*it);
}
// ------------------------------------------------------------------------------------------
bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
{
if( !IOBase::initItem(&p,it,shm,&dlog,myname) )
return false;
if( it.getIntProp(prop_prefix + "rawdata") )
{
p.cal.minRaw = 0;
p.cal.maxRaw = 0;
p.cal.minCal = 0;
p.cal.maxCal = 0;
p.cal.precision = 0;
p.cdiagram = 0;
}
string stype( it.getProp(prop_prefix + "iotype") );
if( !stype.empty() )
{
p.stype = UniSetTypes::getIOType(stype);
if( p.stype == UniversalIO::UnknownIOType )
{
if( dlog )
dlog[Debug::CRIT] << myname << "(IOBase::readItem): неизвестный iotype=: "
<< stype << " for " << it.getProp("name") << endl;
return false;
}
}
string sbit(it.getProp(prop_prefix + "nbit"));
if( !sbit.empty() )
{
p.nbit = UniSetTypes::uni_atoi(sbit.c_str());
if( p.nbit < 0 || p.nbit >= ModbusRTU::BitsPerData )
{
dlog[Debug::CRIT] << myname << "(initRSProperty): BAD nbit=" << p.nbit
<< ". (0 >= nbit < " << ModbusRTU::BitsPerData <<")." << endl;
return false;
}
}
if( p.nbit > 0 &&
( p.stype == UniversalIO::AnalogInput ||
p.stype == UniversalIO::AnalogOutput ) )
{
dlog[Debug::WARN] << "(initRSProperty): (ignore) uncorrect param`s nbit>1 (" << p.nbit << ")"
<< " but iotype=" << p.stype << " for " << it.getProp("name") << endl;
}
string sbyte(it.getProp(prop_prefix + "nbyte"));
if( !sbyte.empty() )
{
p.nbyte = UniSetTypes::uni_atoi(sbyte.c_str());
if( p.nbyte < 0 || p.nbyte > VTypes::Byte::bsize )
{
dlog[Debug::CRIT] << myname << "(initRSProperty): BAD nbyte=" << p.nbyte
<< ". (0 >= nbyte < " << VTypes::Byte::bsize << ")." << endl;
return false;
}
}
string vt(it.getProp(prop_prefix + "vtype"));
if( vt.empty() )
{
p.rnum = VTypes::wsize(VTypes::vtUnknown);
p.vType = VTypes::vtUnknown;
}
else
{
VTypes::VType v(VTypes::str2type(vt));
if( v == VTypes::vtUnknown )
{
dlog[Debug::CRIT] << myname << "(initRSProperty): Unknown tcp_vtype='" << vt << "' for "
<< it.getProp("name")
<< endl;
return false;
}
p.vType = v;
p.rnum = VTypes::wsize(v);
}
return true;
}
// ------------------------------------------------------------------------------------------
bool MBExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, MBExchange::RTUDevice* dev )
{
r->dev = dev;
r->mbval = it.getIntProp("default");
if( dev->dtype == MBExchange::dtRTU )
{
// dlog[Debug::INFO] << myname << "(initRegInfo): init RTU.."
}
else if( dev->dtype == MBExchange::dtMTR )
{
// only for MTR
if( !initMTRitem(it,r) )
return false;
}
else
{
dlog[Debug::CRIT] << myname << "(initRegInfo): Unknown mbtype='" << dev->dtype
<< "' for " << it.getProp("name") << endl;
return false;
}
if( mbregFromID )
{
if( it.getProp("id").empty() )
r->mbreg = conf->getSensorID(it.getProp("name"));
else
r->mbreg = it.getIntProp("id");
}
else
{
string sr = it.getProp(prop_prefix + "mbreg");
if( sr.empty() )
{
dlog[Debug::CRIT] << myname << "(initItem): Unknown 'mbreg' for " << it.getProp("name") << endl;
return false;
}
r->mbreg = ModbusRTU::str2mbData(sr);
}
r->mbfunc = ModbusRTU::fnUnknown;
string f = it.getProp(prop_prefix + "mbfunc");
if( !f.empty() )
{
r->mbfunc = (ModbusRTU::SlaveFunctionCode)UniSetTypes::uni_atoi(f.c_str());
if( r->mbfunc == ModbusRTU::fnUnknown )
{
dlog[Debug::CRIT] << myname << "(initRegInfo): Unknown mbfunc ='" << f
<< "' for " << it.getProp("name") << endl;
return false;
}
}
return true;
}
// ------------------------------------------------------------------------------------------
bool MBExchange::initRTUDevice( RTUDevice* d, UniXML_iterator& it )
{
d->dtype = getDeviceType(it.getProp(prop_prefix + "mbtype"));
if( d->dtype == dtUnknown )
{
dlog[Debug::CRIT] << myname << "(initRTUDevice): Unknown tcp_mbtype=" << it.getProp(prop_prefix + "mbtype")
<< ". Use: rtu "
<< " for " << it.getProp("name") << endl;
return false;
}
string addr = it.getProp(prop_prefix + "mbaddr");
if( addr.empty() )
{
dlog[Debug::CRIT] << myname << "(initRTUDevice): Unknown mbaddr for " << it.getProp("name") << endl;
return false;
}
d->mbaddr = ModbusRTU::str2mbAddr(addr);
return true;
}
// ------------------------------------------------------------------------------------------
bool MBExchange::initItem( UniXML_iterator& it )
{
RSProperty p;
if( !initRSProperty(p,it) )
return false;
string addr = it.getProp(prop_prefix + "mbaddr");
if( addr.empty() )
{
dlog[Debug::CRIT] << myname << "(initItem): Unknown mbaddr='" << addr << "' for " << it.getProp("name") << endl;
return false;
}
ModbusRTU::ModbusAddr mbaddr = ModbusRTU::str2mbAddr(addr);
RTUDevice* dev = addDev(rmap,mbaddr,it);
if( !dev )
{
dlog[Debug::CRIT] << myname << "(initItem): " << it.getProp("name") << " CAN`T ADD for polling!" << endl;
return false;
}
ModbusRTU::ModbusData mbreg;
if( mbregFromID )
mbreg = p.si.id; // conf->getSensorID(it.getProp("name"));
else
{
string reg = it.getProp(prop_prefix + "mbreg");
if( reg.empty() )
{
dlog[Debug::CRIT] << myname << "(initItem): unknown mbreg for " << it.getProp("name") << endl;
return false;
}
mbreg = ModbusRTU::str2mbData(reg);
}
int fn = it.getIntProp(prop_prefix + "mbfunc");
// формула для вычисления ID
// требования:
// - ID > диапазона возможных регитров
// - разные функции должны давать разный ID
RegID rID = genRegID(mbreg,fn);
RegInfo* ri = addReg(dev->regmap,rID,mbreg,it,dev);
if( dev->dtype == dtMTR )
{
p.rnum = MTR::wsize(ri->mtrType);
if( p.rnum <= 0 )
{
dlog[Debug::CRIT] << myname << "(initItem): unknown word size for " << it.getProp("name") << endl;
return false;
}
}
if( !ri )
return false;
ri->dev = dev;
// ПРОВЕРКА!
// если функция на запись, то надо проверить
// что один и тотже регистр не перезапишут несколько датчиков
// это возможно только, если они пишут биты!!
// ИТОГ:
// Если для функций записи список датчиков для регистра > 1
// значит в списке могут быть только битовые датчики
// и если идёт попытка внести в список не битовый датчик то ОШИБКА!
// И наоборот: если идёт попытка внести битовый датчик, а в списке
// уже сидит датчик занимающий целый регистр, то тоже ОШИБКА!
if( ModbusRTU::isWriteFunction(ri->mbfunc) )
{
if( p.nbit<0 && ri->slst.size() > 1 )
{
dlog[Debug::CRIT] << myname << "(initItem): FAILED! Sharing SAVE (not bit saving) to "
<< " tcp_mbreg=" << ModbusRTU::dat2str(ri->mbreg)
<< " for " << it.getProp("name") << endl;
abort(); // ABORT PROGRAM!!!!
return false;
}
if( p.nbit >= 0 && ri->slst.size() == 1 )
{
PList::iterator it2 = ri->slst.begin();
if( it2->nbit < 0 )
{
dlog[Debug::CRIT] << myname << "(initItem): FAILED! Sharing SAVE (mbreg="
<< ModbusRTU::dat2str(ri->mbreg) << " already used)!"
<< " IGNORE --> " << it.getProp("name") << endl;
abort(); // ABORT PROGRAM!!!!
return false;
}
}
// Раз это регистр для записи, то как минимум надо сперва
// инициализировать значением из SM
ri->sm_initOK = it.getIntProp(prop_prefix + "sm_initOK");
ri->mb_initOK = true; // может быть переопределён если будет указан tcp_preinit="1" (см. ниже)
}
else
{
// Если это регистр для чтения, то сразу можно работать
// инициализировать не надо
ri->mb_initOK = true;
ri->sm_initOK = true;
}
RSProperty* p1 = addProp(ri->slst,p);
if( !p1 )
return false;
p1->reg = ri;
if( p1->rnum > 1 )
{
ri->q_count = p1->rnum;
ri->q_num = 1;
for( int i=1; i<p1->rnum; i++ )
{
RegID id1 = genRegID(mbreg+i,ri->mbfunc);
RegInfo* r = addReg(dev->regmap,id1,mbreg+i,it,dev,ri);
r->q_num=i+1;
r->q_count=1;
r->mbfunc = ri->mbfunc;
r->mb_initOK = true;
r->sm_initOK = true;
if( ModbusRTU::isWriteFunction(ri->mbfunc) )
{
// Если занимает несколько регистров, а указана функция записи "одного",
// то это ошибка..
if( ri->mbfunc != ModbusRTU::fnWriteOutputRegisters &&
ri->mbfunc != ModbusRTU::fnForceMultipleCoils )
{
dlog[Debug::CRIT] << myname << "(initItem): Bad write function ='" << ModbusRTU::fnWriteOutputSingleRegister
<< "' for vtype='" << p1->vType << "'"
<< " tcp_mbreg=" << ModbusRTU::dat2str(ri->mbreg)
<< " for " << it.getProp("name") << endl;
abort(); // ABORT PROGRAM!!!!
return false;
}
}
}
}
// Фомируем список инициализации
bool need_init = it.getIntProp(prop_prefix + "preinit");
if( need_init && ModbusRTU::isWriteFunction(ri->mbfunc) )
{
InitRegInfo ii;
ii.p = p;
ii.dev = dev;
ii.ri = ri;
string s_reg(it.getProp(prop_prefix + "init_mbreg"));
if( !s_reg.empty() )
ii.mbreg = ModbusRTU::str2mbData(s_reg);
else
ii.mbreg = ri->mbreg;
string s_mbfunc(it.getProp(prop_prefix + "init_mbfunc"));
if( !s_mbfunc.empty() )
{
ii.mbfunc = (ModbusRTU::SlaveFunctionCode)UniSetTypes::uni_atoi(s_mbfunc);
if( ii.mbfunc == ModbusRTU::fnUnknown )
{
dlog[Debug::CRIT] << myname << "(initItem): Unknown tcp_init_mbfunc ='" << s_mbfunc
<< "' for " << it.getProp("name") << endl;
return false;
}
}
else
{
switch(ri->mbfunc)
{
case ModbusRTU::fnWriteOutputSingleRegister:
ii.mbfunc = ModbusRTU::fnReadOutputRegisters;
break;
case ModbusRTU::fnForceSingleCoil:
ii.mbfunc = ModbusRTU::fnReadCoilStatus;
break;
case ModbusRTU::fnWriteOutputRegisters:
ii.mbfunc = ModbusRTU::fnReadOutputRegisters;
break;
case ModbusRTU::fnForceMultipleCoils:
ii.mbfunc = ModbusRTU::fnReadCoilStatus;
break;
default:
ii.mbfunc = ModbusRTU::fnReadOutputRegisters;
break;
}
}
initRegList.push_back(ii);
ri->mb_initOK = false;
ri->sm_initOK = false;
}
return true;
}
// ------------------------------------------------------------------------------------------
bool MBExchange::initMTRitem( UniXML_iterator& it, RegInfo* p )
{
p->mtrType = MTR::str2type(it.getProp("mtrtype"));
if( p->mtrType == MTR::mtUnknown )
{
dlog[Debug::CRIT] << myname << "(readMTRItem): Unknown mtrtype '"
<< it.getProp("mtrtype")
<< "' for " << it.getProp("name") << endl;
return false;
}
return true;
}
// ------------------------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, const MBExchange::DeviceType& dt )
{
switch(dt)
{
case MBExchange::dtRTU:
os << "RTU";
break;
case MBExchange::dtMTR:
os << "MTR";
break;
case MBExchange::dtRTU188:
os << "RTU188";
break;
default:
os << "Unknown device type (" << (int)dt << ")";
break;
}
return os;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, const MBExchange::RSProperty& p )
{
os << " (" << ModbusRTU::dat2str(p.reg->mbreg) << ")"
<< " sid=" << p.si.id
<< " stype=" << p.stype
<< " nbit=" << p.nbit
<< " nbyte=" << p.nbyte
<< " rnum=" << p.rnum
<< " safety=" << p.safety
<< " invert=" << p.invert;
if( p.stype == UniversalIO::AnalogInput || p.stype == UniversalIO::AnalogOutput )
{
os << p.cal
<< " cdiagram=" << ( p.cdiagram ? "yes" : "no" );
}
return os;
}
// -----------------------------------------------------------------------------
void MBExchange::initDeviceList()
{
xmlNode* respNode = conf->findNode(cnode,"DeviceList");
if( respNode )
{
UniXML_iterator it1(respNode);
if( it1.goChildren() )
{
for(;it1.getCurrent(); it1.goNext() )
{
ModbusRTU::ModbusAddr a = ModbusRTU::str2mbAddr(it1.getProp("addr"));
initDeviceInfo(rmap,a,it1);
}
}
else
dlog[Debug::WARN] << myname << "(init): <DeviceList> empty section..." << endl;
}
else
dlog[Debug::WARN] << myname << "(init): <DeviceList> not found..." << endl;
}
// -----------------------------------------------------------------------------
bool MBExchange::initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXML_iterator& it )
{
RTUDeviceMap::iterator d = m.find(a);
if( d == m.end() )
{
dlog[Debug::WARN] << myname << "(initDeviceInfo): not found device for addr=" << ModbusRTU::addr2str(a) << endl;
return false;
}
d->second->ask_every_reg = it.getIntProp("ask_every_reg");
dlog[Debug::INFO] << myname << "(initDeviceInfo): add addr=" << ModbusRTU::addr2str(a)
<< " ask_every_reg=" << d->second->ask_every_reg << endl;
string s(it.getProp("respondSensor"));
if( !s.empty() )
{
d->second->resp_id = conf->getSensorID(s);
if( d->second->resp_id == DefaultObjectId )
{
dlog[Debug::CRIT] << myname << "(initDeviceInfo): not found ID for noRespondSensor=" << s << endl;
return false;
}
}
dlog[Debug::INFO] << myname << "(initDeviceInfo): add addr=" << ModbusRTU::addr2str(a) << endl;
int tout = it.getPIntProp("timeout",5000);
d->second->resp_ptTimeout.setTiming(tout);
d->second->resp_invert = it.getIntProp("invert");
// d->second->no_clean_input = it.getIntProp("no_clean_input");
// dlog[Debug::INFO] << myname << "(initDeviceInfo): add " << (*d->second) << endl;
return true;
}
// -----------------------------------------------------------------------------
bool MBExchange::activateObject()
{
// блокирование обработки Starsp
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
setProcActive(false);
UniSetTypes::uniset_mutex_lock l(mutex_start, 5000);
UniSetObject_LT::activateObject();
if( !shm->isLocalwork() )
rtuQueryOptimization(rmap);
initIterators();
setProcActive(true);
}
return true;
}
// ------------------------------------------------------------------------------------------
void MBExchange::processingMessage(UniSetTypes::VoidMessage *msg)
{
try
{
switch(msg->type)
{
case UniSetTypes::Message::SysCommand:
{
UniSetTypes::SystemMessage sm( msg );
sysCommand( &sm );
}
break;
case Message::Timer:
{
TimerMessage tm(msg);
timerInfo(&tm);
}
break;
case Message::SensorInfo:
{
SensorMessage sm( msg );
sensorInfo(&sm);
}
break;
default:
break;
}
}
catch( SystemError& ex )
{
dlog[Debug::CRIT] << myname << "(SystemError): " << ex << std::endl;
// throw SystemError(ex);
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << myname << "(processingMessage): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(processingMessage): catch ...\n";
}
}
// -----------------------------------------------------------------------------
void MBExchange::sysCommand( UniSetTypes::SystemMessage *sm )
{
switch( sm->command )
{
case SystemMessage::StartUp:
{
if( rmap.empty() )
{
dlog[Debug::CRIT] << myname << "(sysCommand): ************* ITEM MAP EMPTY! terminated... *************" << endl;
raise(SIGTERM);
return;
}
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(sysCommand): device map size= " << rmap.size() << endl;
if( !shm->isLocalwork() )
initDeviceList();
waitSMReady();
// подождать пока пройдёт инициализация датчиков
// см. activateObject()
msleep(initPause);
PassiveTimer ptAct(activateTimeout);
while( !activated && !ptAct.checkTime() )
{
cout << myname << "(sysCommand): wait activate..." << endl;
msleep(300);
if( activated )
break;
}
if( !activated )
dlog[Debug::CRIT] << myname << "(sysCommand): ************* don`t activate?! ************" << endl;
{
UniSetTypes::uniset_mutex_lock l(mutex_start, 10000);
askSensors(UniversalIO::UIONotify);
initOutput();
}
askTimer(tmExchange,polltime);
break;
}
case SystemMessage::FoldUp:
case SystemMessage::Finish:
askSensors(UniversalIO::UIODontNotify);
break;
case SystemMessage::WatchDog:
{
// ОПТИМИЗАЦИЯ (защита от двойного перезаказа при старте)
// Если идёт локальная работа
// (т.е. MBExchange запущен в одном процессе с SharedMemory2)
// то обрабатывать WatchDog не надо, т.к. мы и так ждём готовности SM
// при заказе датчиков, а если SM вылетит, то вместе с этим процессом(MBExchange)
if( shm->isLocalwork() )
break;
askSensors(UniversalIO::UIONotify);
initOutput();
if( !force )
{
uniset_mutex_lock l(pollMutex,2000);
force = true;
poll();
force = false;
}
}
break;
case SystemMessage::LogRotate:
{
// переоткрываем логи
unideb << myname << "(sysCommand): logRotate" << std::endl;
string fname = unideb.getLogFile();
if( !fname.empty() )
{
unideb.logFile(fname);
unideb << myname << "(sysCommand): ***************** UNIDEB LOG ROTATE *****************" << std::endl;
}
dlog << myname << "(sysCommand): logRotate" << std::endl;
fname = dlog.getLogFile();
if( !fname.empty() )
{
dlog.logFile(fname);
dlog << myname << "(sysCommand): ***************** dlog LOG ROTATE *****************" << std::endl;
}
}
break;
default:
break;
}
}
// ------------------------------------------------------------------------------------------
void MBExchange::initOutput()
{
}
// ------------------------------------------------------------------------------------------
void MBExchange::askSensors( UniversalIO::UIOCommand cmd )
{
if( !shm->waitSMworking(test_id,activateTimeout,50) )
{
ostringstream err;
err << myname
<< "(askSensors): Не дождались готовности(work) SharedMemory к работе в течение "
<< activateTimeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
kill(SIGTERM,getpid()); // прерываем (перезапускаем) процесс...
throw SystemError(err.str());
}
if( force_out )
return;
try
{
if( sidExchangeMode != DefaultObjectId )
shm->askSensor(sidExchangeMode,cmd);
}
catch( UniSetTypes::Exception& ex )
{
dlog[Debug::WARN] << myname << "(askSensors): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::WARN] << myname << "(askSensors): 'sidExchangeMode' catch..." << std::endl;
}
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
if( !isWriteFunction(it->second->mbfunc) )
continue;
for( PList::iterator i=it->second->slst.begin(); i!=it->second->slst.end(); ++i )
{
try
{
shm->askSensor(i->si.id,cmd);
}
catch( UniSetTypes::Exception& ex )
{
dlog[Debug::WARN] << myname << "(askSensors): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::WARN] << myname << "(askSensors): catch..." << std::endl;
}
}
}
}
}
// ------------------------------------------------------------------------------------------
void MBExchange::sensorInfo( UniSetTypes::SensorMessage* sm )
{
if( force_out )
return;
if( sm->id == sidExchangeMode )
{
exchangeMode = sm->value;
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(sensorInfo): exchange MODE=" << sm->value << std::endl;
return;
}
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
if( !isWriteFunction(it->second->mbfunc) )
continue;
for( PList::iterator i=it->second->slst.begin(); i!=it->second->slst.end(); ++i )
{
if( sm->id == i->si.id && sm->node == i->si.node )
{
if( dlog.debugging(Debug::INFO) )
{
dlog[Debug::INFO] << myname<< "(sensorInfo): si.id=" << sm->id
<< " reg=" << ModbusRTU::dat2str(i->reg->mbreg)
<< " val=" << sm->value
<< " mb_initOK=" << i->reg->mb_initOK << endl;
}
if( !i->reg->mb_initOK )
continue;
i->value = sm->value;
updateRSProperty( &(*i),true );
return;
}
}
}
}
}
// ------------------------------------------------------------------------------------------
void MBExchange::timerInfo( TimerMessage *tm )
{
if( tm->id == tmExchange )
{
if( no_extimer )
askTimer(tm->id,0);
else
step();
}
}
// -----------------------------------------------------------------------------
void MBExchange::poll()
{
if( !mb )
{
{
uniset_mutex_lock l(pollMutex, 300);
pollActivated = false;
mb = initMB(false);
if( !mb )
{
for( MBExchange::RTUDeviceMap::iterator it=rmap.begin(); it!=rmap.end(); ++it )
it->second->resp_real = false;
}
}
if( !checkProcActive() )
return;
updateSM();
allInitOK = false;
return;
}
{
uniset_mutex_lock l(pollMutex);
pollActivated = true;
ptTimeout.reset();
}
if( !allInitOK )
firstInitRegisters();
if( !checkProcActive() )
return;
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(poll): ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " regs=" << d->regmap.size() << endl;
d->resp_real = false;
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
if( !checkProcActive() )
return;
try
{
if( d->dtype==MBExchange::dtRTU || d->dtype==MBExchange::dtMTR )
{
if( pollRTU(d,it) )
d->resp_real = true;
}
}
catch( ModbusRTU::mbException& ex )
{
// if( d->resp_real )
// {
if( dlog.debugging(Debug::LEVEL3) )
{
dlog[Debug::LEVEL3] << myname << "(poll): FAILED ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " reg=" << ModbusRTU::dat2str(it->second->mbreg)
<< " for sensors: "; print_plist(dlog(Debug::LEVEL3),it->second->slst);
dlog(Debug::LEVEL3) << " err: " << ex << endl;
}
// }
// d->resp_real = false;
if( ex.err == ModbusRTU::erTimeOut && !d->ask_every_reg )
break;
// если контроллер хоть что-то ответил, то вроде как связь есть..
if( ex.err != ModbusRTU::erTimeOut )
d->resp_real = true;
}
if( it==d->regmap.end() )
break;
if( !checkProcActive() )
return;
}
if( stat_time > 0 )
poll_count++;
}
if( stat_time > 0 && ptStatistic.checkTime() )
{
cout << endl << "(poll statistic): number of calls is " << poll_count << " (poll time: " << stat_time << " sec)" << endl << endl;
ptStatistic.reset();
poll_count=0;
}
{
uniset_mutex_lock l(pollMutex);
pollActivated = false;
}
if( !checkProcActive() )
return;
// update SharedMemory...
updateSM();
// check thresholds
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
if( !checkProcActive() )
return;
RegInfo* r(it->second);
for( PList::iterator i=r->slst.begin(); i!=r->slst.end(); ++i )
IOBase::processingThreshold( &(*i),shm,force);
}
}
// printMap(rmap);
}
// -----------------------------------------------------------------------------
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment