Commit dd707c2b authored by Pavel Vainerman's avatar Pavel Vainerman

(MBExchange): начал выносить в базовый класс одинаковый код для MBTCPMaster и RTUExchange

parent 774daea9
...@@ -12,20 +12,11 @@ using namespace UniSetExtensions; ...@@ -12,20 +12,11 @@ using namespace UniSetExtensions;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
MBTCPMaster::MBTCPMaster( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, MBTCPMaster::MBTCPMaster( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId,
SharedMemory* ic, const std::string prefix ): SharedMemory* ic, const std::string prefix ):
UniSetObject_LT(objId), MBExchange(objId,shmId,ic,prefix),
allInitOK(false), allInitOK(false),
mb(0), mb(0),
shm(0),
initPause(0),
force(false),
force_out(false),
mbregFromID(false),
sidExchangeMode(DefaultObjectId),
activated(false),
noQueryOptimization(false),
force_disconnect(true),
prefix(prefix),
no_extimer(false), no_extimer(false),
force_disconnect(true),
poll_count(0), poll_count(0),
pollThread(0) pollThread(0)
{ {
...@@ -34,27 +25,8 @@ pollThread(0) ...@@ -34,27 +25,8 @@ pollThread(0)
if( objId == DefaultObjectId ) if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(MBTCPMaster): objId=-1?!! Use --" + prefix + "-name" ); throw UniSetTypes::SystemError("(MBTCPMaster): 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("(MBTCPMaster): Not found node <" + conf_name + " ...> for " + myname );
shm = new SMInterface(shmId,&ui,objId,ic);
UniXML_iterator it(cnode); 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);
// ---------- init MBTCP ---------- // ---------- init MBTCP ----------
string pname("--" + prefix + "-gateway-iaddr"); string pname("--" + prefix + "-gateway-iaddr");
iaddr = conf->getArgParam(pname,it.getProp("gateway_iaddr")); iaddr = conf->getArgParam(pname,it.getProp("gateway_iaddr"));
...@@ -67,29 +39,14 @@ pollThread(0) ...@@ -67,29 +39,14 @@ pollThread(0)
throw UniSetTypes::SystemError(myname+"(MBMaster): Unknown inet port...(Use: " + tmp +")" ); throw UniSetTypes::SystemError(myname+"(MBMaster): Unknown inet port...(Use: " + tmp +")" );
force_disconnect = conf->getArgInt("--" + prefix + "-persistent-connection",it.getProp("persistent_connection")) ? false : true;
dlog[Debug::INFO] << myname << "(init): persisten-connection=" << (!force_disconnect) << endl;
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);
ptTimeout.setTiming(tout); 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"));
force_disconnect = conf->getArgInt("--" + prefix + "-persistent-connection",it.getProp("persistent_connection")) ? false : true;
dlog[Debug::INFO] << myname << "(init): persisten-connection=" << (!force_disconnect) << endl;
if( shm->isLocalwork() ) if( shm->isLocalwork() )
{ {
readConfiguration(); readConfiguration();
...@@ -99,60 +56,6 @@ pollThread(0) ...@@ -99,60 +56,6 @@ pollThread(0)
else else
ic->addReadItem( sigc::mem_fun(this,&MBTCPMaster::readItem) ); ic->addReadItem( sigc::mem_fun(this,&MBTCPMaster::readItem) );
// ********** 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);
if( dlog.debugging(Debug::INFO) )
printMap(rmap);
poll_count = -1;
pollThread = new ThreadCreator<MBTCPMaster>(this, &MBTCPMaster::poll_thread); pollThread = new ThreadCreator<MBTCPMaster>(this, &MBTCPMaster::poll_thread);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -169,7 +72,6 @@ MBTCPMaster::~MBTCPMaster() ...@@ -169,7 +72,6 @@ MBTCPMaster::~MBTCPMaster()
delete pollThread; delete pollThread;
delete mb; delete mb;
delete shm;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MBTCPMaster::initMB( bool reopen ) void MBTCPMaster::initMB( bool reopen )
...@@ -216,24 +118,6 @@ void MBTCPMaster::initMB( bool reopen ) ...@@ -216,24 +118,6 @@ void MBTCPMaster::initMB( bool reopen )
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MBTCPMaster::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 MBTCPMaster::timerInfo( TimerMessage *tm ) void MBTCPMaster::timerInfo( TimerMessage *tm )
{ {
if( tm->id == tmExchange ) if( tm->id == tmExchange )
...@@ -248,25 +132,8 @@ void MBTCPMaster::timerInfo( TimerMessage *tm ) ...@@ -248,25 +132,8 @@ void MBTCPMaster::timerInfo( TimerMessage *tm )
void MBTCPMaster::step() void MBTCPMaster::step()
{ {
updateRespondSensors(); updateRespondSensors();
MBExchange::step();
if( !activated )
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;
}
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MBTCPMaster::updateRespondSensors() void MBTCPMaster::updateRespondSensors()
{ {
...@@ -338,18 +205,6 @@ void MBTCPMaster::poll_thread() ...@@ -338,18 +205,6 @@ void MBTCPMaster::poll_thread()
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool MBTCPMaster::checkProcActive()
{
uniset_mutex_lock l(actMutex, 300);
return activated;
}
// -----------------------------------------------------------------------------
void MBTCPMaster::setProcActive( bool st )
{
uniset_mutex_lock l(actMutex, 400);
activated = st;
}
// -----------------------------------------------------------------------------
void MBTCPMaster::poll() void MBTCPMaster::poll()
{ {
if( !mb ) if( !mb )
...@@ -502,20 +357,8 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it ) ...@@ -502,20 +357,8 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
} }
} }
if( exchangeMode == emWriteOnly && !ModbusRTU::isWriteFunction(p->mbfunc) ) if( !checkPoll(ModbusRTU::isWriteFunction(p->mbfunc)) )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): skip.. mode='emWriteOnly'" << endl;
return true; return true;
}
if( exchangeMode == emReadOnly && ModbusRTU::isWriteFunction(p->mbfunc) )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): skip.. poll mode='emReadOnly'" << endl;
return false;
}
if( p->q_count == 0 ) if( p->q_count == 0 )
{ {
...@@ -1317,41 +1160,6 @@ void MBTCPMaster::sigterm( int signo ) ...@@ -1317,41 +1160,6 @@ void MBTCPMaster::sigterm( int signo )
UniSetObject_LT::sigterm(signo); UniSetObject_LT::sigterm(signo);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void MBTCPMaster::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 MBTCPMaster::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
{
if( UniSetTypes::check_filter(it,s_field,s_fvalue) )
initItem(it);
return true;
}
// ------------------------------------------------------------------------------------------
MBTCPMaster::RTUDevice* MBTCPMaster::addDev( RTUDeviceMap& mp, ModbusRTU::ModbusAddr a, UniXML_iterator& xmlit ) MBTCPMaster::RTUDevice* MBTCPMaster::addDev( RTUDeviceMap& mp, ModbusRTU::ModbusAddr a, UniXML_iterator& xmlit )
{ {
RTUDeviceMap::iterator it = mp.find(a); RTUDeviceMap::iterator it = mp.find(a);
...@@ -1599,20 +1407,6 @@ bool MBTCPMaster::initRegInfo( RegInfo* r, UniXML_iterator& it, MBTCPMaster::RT ...@@ -1599,20 +1407,6 @@ bool MBTCPMaster::initRegInfo( RegInfo* r, UniXML_iterator& it, MBTCPMaster::RT
return true; return true;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
MBTCPMaster::DeviceType MBTCPMaster::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;
}
// ------------------------------------------------------------------------------------------
bool MBTCPMaster::initRTUDevice( RTUDevice* d, UniXML_iterator& it ) bool MBTCPMaster::initRTUDevice( RTUDevice* d, UniXML_iterator& it )
{ {
d->dtype = getDeviceType(it.getProp("tcp_mbtype")); d->dtype = getDeviceType(it.getProp("tcp_mbtype"));
...@@ -1881,9 +1675,7 @@ bool MBTCPMaster::initMTRitem( UniXML_iterator& it, RegInfo* p ) ...@@ -1881,9 +1675,7 @@ bool MBTCPMaster::initMTRitem( UniXML_iterator& it, RegInfo* p )
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void MBTCPMaster::initIterators() void MBTCPMaster::initIterators()
{ {
shm->initAIterator(aitHeartBeat); MBExchange::initIterators();
shm->initAIterator(aitExchangeMode);
for( MBTCPMaster::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 ) for( MBTCPMaster::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
...@@ -1903,32 +1695,19 @@ void MBTCPMaster::initIterators() ...@@ -1903,32 +1695,19 @@ void MBTCPMaster::initIterators()
void MBTCPMaster::help_print( int argc, const char* const* argv ) void MBTCPMaster::help_print( int argc, const char* const* argv )
{ {
cout << "Default: prefix='mbtcp'" << endl; cout << "Default: prefix='mbtcp'" << endl;
cout << "--prefix-name name - ObjectId (имя) процесса. По умолчанию: MBTCPMaster1" << endl; MBExchange::help_print(argc,argv);
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;
// ---------- init MBTCP ---------- // ---------- init MBTCP ----------
// cout << "--prefix-sm-ready-timeout - время на ожидание старта SM" << endl; // cout << "--prefix-sm-ready-timeout - время на ожидание старта SM" << endl;
cout << " Настройки протокола TCP: " << endl; cout << " Настройки протокола TCP: " << endl;
cout << "--prefix-gateway hostname,IP - IP опрашиваемого узла" << endl; cout << "--prefix-gateway hostname,IP - IP опрашиваемого узла" << endl;
cout << "--prefix-gateway-port num - port на опрашиваемом узле" << endl; cout << "--prefix-gateway-port num - port на опрашиваемом узле" << endl;
cout << "--prefix-recv-timeout msec - Таймаут на приём одного сообщения." << endl; cout << "--prefix-recv-timeout msec - Таймаут на приём одного сообщения" << endl;
cout << "--prefix-timeout msec - Таймаут для определения отсутсвия соединения" << endl; cout << "--prefix-timeout msec - Таймаут для определения отсутсвия соединения" << endl;
cout << "--prefix-persistent-connection 0,1 - Не закрывать соединение на каждом цикле опроса" << endl; cout << "--prefix-persistent-connection 0,1 - Не закрывать соединение на каждом цикле опроса" << endl;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
MBTCPMaster* MBTCPMaster::init_mbmaster( int argc, const char* const* argv, UniSetTypes::ObjectId icID, SharedMemory* ic, MBTCPMaster* MBTCPMaster::init_mbmaster( int argc, const char* const* argv,
UniSetTypes::ObjectId icID, SharedMemory* ic,
const std::string prefix ) const std::string prefix )
{ {
string name = conf->getArgParam("--" + prefix + "-name","MBTCPMaster1"); string name = conf->getArgParam("--" + prefix + "-name","MBTCPMaster1");
...@@ -2069,18 +1848,18 @@ std::ostream& operator<<( std::ostream& os, MBTCPMaster::RTUDeviceMap& m ) ...@@ -2069,18 +1848,18 @@ std::ostream& operator<<( std::ostream& os, MBTCPMaster::RTUDeviceMap& m )
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBTCPMaster::RTUDevice& d ) std::ostream& operator<<( std::ostream& os, MBTCPMaster::RTUDevice& d )
{ {
os << "addr=" << ModbusRTU::addr2str(d.mbaddr) os << "addr=" << ModbusRTU::addr2str(d.mbaddr)
<< " type=" << d.dtype << " type=" << d.dtype
<< " respond_id=" << d.resp_id << " respond_id=" << d.resp_id
<< " respond_timeout=" << d.resp_ptTimeout.getInterval() << " respond_timeout=" << d.resp_ptTimeout.getInterval()
<< " respond_state=" << d.resp_state << " respond_state=" << d.resp_state
<< " respond_invert=" << d.resp_invert << " respond_invert=" << d.resp_invert
<< endl; << endl;
os << " regs: " << endl; os << " regs: " << endl;
for( MBTCPMaster::RegMap::iterator it=d.regmap.begin(); it!=d.regmap.end(); ++it ) for( MBTCPMaster::RegMap::iterator it=d.regmap.begin(); it!=d.regmap.end(); ++it )
os << " " << *(it->second) << endl; os << " " << *(it->second) << endl;
return os; return os;
} }
...@@ -2187,29 +1966,8 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -2187,29 +1966,8 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
if( !save && write_only ) if( !save && write_only )
return; return;
if( save && exchangeMode == emReadOnly ) if( !checkUpdateSM(save) )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "updateP: sid=" << p->si.id
<< " skip... mode='emReadOnly' " << endl;
return;
}
if( !save && exchangeMode == emWriteOnly )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "updateP: sid=" << p->si.id
<< " skip... mode='emWriteOnly' " << endl;
return; return;
}
if( save && exchangeMode == emSkipSaveToSM )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "updateP: sid=" << p->si.id
<< " skip... mode='emSkipSaveToSM' " << endl;
return;
}
// если требуется инициализация и она ещё не произведена, // если требуется инициализация и она ещё не произведена,
// то игнорируем // то игнорируем
......
...@@ -5,19 +5,8 @@ ...@@ -5,19 +5,8 @@
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <vector>
#include "IONotifyController.h" #include "MBExchange.h"
#include "UniSetObject_LT.h"
#include "modbus/ModbusTCPMaster.h" #include "modbus/ModbusTCPMaster.h"
#include "PassiveTimer.h"
#include "Trigger.h"
#include "Mutex.h"
#include "Calibration.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "IOBase.h"
#include "VTypes.h"
#include "MTR.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/*! /*!
\page page_ModbusTCP Реализация ModbusTCP master \page page_ModbusTCP Реализация ModbusTCP master
...@@ -190,7 +179,7 @@ ...@@ -190,7 +179,7 @@
связи обновляется в основном потоке (чтобы не зависеть от TCP). связи обновляется в основном потоке (чтобы не зависеть от TCP).
*/ */
class MBTCPMaster: class MBTCPMaster:
public UniSetObject_LT public MBExchange
{ {
public: public:
MBTCPMaster( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0, MBTCPMaster( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0,
...@@ -207,32 +196,12 @@ class MBTCPMaster: ...@@ -207,32 +196,12 @@ class MBTCPMaster:
void execute(); void execute();
static const int NoSafetyState=-1;
/*! Режимы работы процесса обмена */
enum ExchangeMode
{
emNone, /*!< нормальная работа (по умолчанию) */
emWriteOnly, /*!< "только посылка данных" (работают только write-функции) */
emReadOnly, /*!< "только чтение" (работают только read-функции) */
emSkipSaveToSM /*!< не писать данные в SM (при этом работают и read и write функции */
};
enum Timer enum Timer
{ {
tmExchange tmExchange
}; };
enum DeviceType // -----------------------------------------------------
{
dtUnknown, /*!< неизвестный */
dtRTU, /*!< RTU (default) */
dtMTR /*!< MTR (DEIF) */
};
static DeviceType getDeviceType( const std::string dtype );
friend std::ostream& operator<<( std::ostream& os, const DeviceType& dt );
// -------------------------------------------------------------------------------
struct RTUDevice; struct RTUDevice;
struct RegInfo; struct RegInfo;
...@@ -347,7 +316,6 @@ class MBTCPMaster: ...@@ -347,7 +316,6 @@ class MBTCPMaster:
// ---------------------------------- // ----------------------------------
static RegID genRegID( const ModbusRTU::ModbusData r, const int fn ); static RegID genRegID( const ModbusRTU::ModbusData r, const int fn );
protected: protected:
struct InitRegInfo struct InitRegInfo
{ {
...@@ -380,13 +348,7 @@ class MBTCPMaster: ...@@ -380,13 +348,7 @@ class MBTCPMaster:
int port; int port;
int recv_timeout; int recv_timeout;
xmlNode* cnode; virtual void step();
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void step();
void poll_thread(); void poll_thread();
void poll(); void poll();
bool pollRTU( RTUDevice* dev, RegMap::iterator& it ); bool pollRTU( RTUDevice* dev, RegMap::iterator& it );
...@@ -403,17 +365,12 @@ class MBTCPMaster: ...@@ -403,17 +365,12 @@ class MBTCPMaster:
void timerInfo( UniSetTypes::TimerMessage *tm ); void timerInfo( UniSetTypes::TimerMessage *tm );
void askSensors( UniversalIO::UIOCommand cmd ); void askSensors( UniversalIO::UIOCommand cmd );
void initOutput(); void initOutput();
void waitSMReady(); void initMB( bool reopen=false );
virtual bool activateObject(); virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo ); virtual void sigterm( int signo );
virtual void initIterators();
void initMB( bool reopen=false ); virtual bool initItem( UniXML_iterator& it );
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
void initDeviceList(); void initDeviceList();
void initOffsetList(); void initOffsetList();
...@@ -430,47 +387,16 @@ class MBTCPMaster: ...@@ -430,47 +387,16 @@ class MBTCPMaster:
void rtuQueryOptimization( RTUDeviceMap& m ); void rtuQueryOptimization( RTUDeviceMap& m );
void readConfiguration();
bool checkProcActive();
void setProcActive( bool st );
private:
MBTCPMaster();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
bool force; /*!< флаг означающий, что надо сохранять в SM, даже если значение не менялось */
bool force_out; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID;
int polltime; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_usec;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
UniSetTypes::ObjectId sidExchangeMode; /*!< иденидентификатор для датчика режима работы */
IOController::AIOStateList::iterator aitExchangeMode;
long exchangeMode; /*!< режим работы см. ExchangeMode */
UniSetTypes::uniset_mutex actMutex;
bool activated;
int activateTimeout;
bool noQueryOptimization;
bool force_disconnect;
std::string prefix;
bool no_extimer; bool no_extimer;
bool force_disconnect;
timeout_t stat_time; /*!< время сбора статистики обмена */ timeout_t stat_time; /*!< время сбора статистики обмена */
int poll_count; int poll_count;
PassiveTimer ptStatistic; /*!< таймер для сбора статистики обмена */ PassiveTimer ptStatistic; /*!< таймер для сбора статистики обмена */
private:
MBTCPMaster();
// т.к. TCP может "зависнуть" на подключении к недоступному узлу // т.к. TCP может "зависнуть" на подключении к недоступному узлу
// делаем опрос в отдельном потоке // делаем опрос в отдельном потоке
ThreadCreator<MBTCPMaster>* pollThread; /*!< поток опроса */ ThreadCreator<MBTCPMaster>* pollThread; /*!< поток опроса */
......
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <cmath> #include <cmath>
#include <sstream> #include <sstream>
#include "Exceptions.h"
#include "Extensions.h" #include "Extensions.h"
#include "RTUExchange.h" #include "RTUExchange.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -11,40 +10,19 @@ using namespace UniSetExtensions; ...@@ -11,40 +10,19 @@ using namespace UniSetExtensions;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
RTUExchange::RTUExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic, RTUExchange::RTUExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic,
const std::string prefix_ ): const std::string prefix_ ):
UniSetObject_LT(objId), MBExchange(objId,shmId,ic,prefix_),
mb(0), mb(0),
defSpeed(ComPort::ComSpeed0), defSpeed(ComPort::ComSpeed0),
use485F(false), use485F(false),
transmitCtl(false), transmitCtl(false),
shm(0),
initPause(0),
force(false),
force_out(false),
mbregFromID(false),
activated(false),
rs_pre_clean(false), rs_pre_clean(false),
noQueryOptimization(false), allNotRespond(false)
allNotRespond(false),
prefix(prefix_)
{ {
if( objId == DefaultObjectId ) if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(RTUExchange): objId=-1?!! Use --" + prefix + "-name" ); throw UniSetTypes::SystemError("(RTUExchange): objId=-1?!! Use --" + prefix + "-name" );
// xmlNode* cnode = conf->getNode(myname);
cnode = conf->getNode(myname);
if( cnode == NULL )
throw UniSetTypes::SystemError("(RTUExchange): Not find conf-node for " + myname );
shm = new SMInterface(shmId,&ui,objId,ic);
UniXML_iterator it(cnode); 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;
// ---------- init RS ---------- // ---------- init RS ----------
// UniXML_iterator it(cnode); // UniXML_iterator it(cnode);
devname = conf->getArgParam("--"+prefix+"-dev",it.getProp("device")); devname = conf->getArgParam("--"+prefix+"-dev",it.getProp("device"));
...@@ -69,16 +47,6 @@ prefix(prefix_) ...@@ -69,16 +47,6 @@ prefix(prefix_)
rs_pre_clean = conf->getArgInt("--"+prefix+"-pre-clean",it.getProp("pre_clean")); rs_pre_clean = conf->getArgInt("--"+prefix+"-pre-clean",it.getProp("pre_clean"));
noQueryOptimization = conf->getArgInt("--"+prefix+"-no-query-optimization",it.getProp("no_query_optimization")); noQueryOptimization = conf->getArgInt("--"+prefix+"-no-query-optimization",it.getProp("no_query_optimization"));
mbregFromID = conf->getArgInt("--mbs-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);
force = conf->getArgInt("--"+prefix+"-force",it.getProp("force"));
force_out = conf->getArgInt("--"+prefix+"-force-out",it.getProp("force_out"));
if( shm->isLocalwork() ) if( shm->isLocalwork() )
{ {
readConfiguration(); readConfiguration();
...@@ -88,48 +56,11 @@ prefix(prefix_) ...@@ -88,48 +56,11 @@ prefix(prefix_)
else else
ic->addReadItem( sigc::mem_fun(this,&RTUExchange::readItem) ); ic->addReadItem( sigc::mem_fun(this,&RTUExchange::readItem) );
// ********** 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;
activateTimeout = conf->getArgPInt("--"+prefix+"-activate-timeout", 20000);
initMB(false); initMB(false);
printMap(rmap); if( dlog.debugging(Debug::INFO) )
// abort(); printMap(rmap);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
RTUExchange::~RTUExchange() RTUExchange::~RTUExchange()
...@@ -150,7 +81,6 @@ RTUExchange::~RTUExchange() ...@@ -150,7 +81,6 @@ RTUExchange::~RTUExchange()
} }
delete mb; delete mb;
delete shm;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void RTUExchange::initMB( bool reopen ) void RTUExchange::initMB( bool reopen )
...@@ -198,24 +128,6 @@ void RTUExchange::initMB( bool reopen ) ...@@ -198,24 +128,6 @@ void RTUExchange::initMB( bool reopen )
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void RTUExchange::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): Не дождались готовности SharedMemory к работе в течение " << ready_timeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
throw SystemError(err.str());
}
}
// -----------------------------------------------------------------------------
void RTUExchange::timerInfo( TimerMessage *tm ) void RTUExchange::timerInfo( TimerMessage *tm )
{ {
if( tm->id == tmExchange ) if( tm->id == tmExchange )
...@@ -229,22 +141,7 @@ void RTUExchange::step() ...@@ -229,22 +141,7 @@ void RTUExchange::step()
poll(); poll();
} }
if( !activated ) MBExchange::step();
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;
}
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -388,7 +285,10 @@ bool RTUExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it ) ...@@ -388,7 +285,10 @@ bool RTUExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
<< " mb_init=" << p->mb_init << " mb_init=" << p->mb_init
<< endl; << endl;
} }
if( !checkPoll(ModbusRTU::isWriteFunction(p->mbfunc)) )
return true;
if( p->q_count == 0 ) if( p->q_count == 0 )
{ {
if( dlog.debugging(Debug::INFO) ) if( dlog.debugging(Debug::INFO) )
...@@ -886,6 +786,8 @@ void RTUExchange::sensorInfo( UniSetTypes::SensorMessage* sm ) ...@@ -886,6 +786,8 @@ void RTUExchange::sensorInfo( UniSetTypes::SensorMessage* sm )
if( force_out ) if( force_out )
return; return;
MBExchange::sensorInfo(sm);
for( RTUExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 ) for( RTUExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{ {
RTUDevice* d(it1->second); RTUDevice* d(it1->second);
...@@ -939,45 +841,9 @@ bool RTUExchange::activateObject() ...@@ -939,45 +841,9 @@ bool RTUExchange::activateObject()
void RTUExchange::sigterm( int signo ) void RTUExchange::sigterm( int signo )
{ {
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl; cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false; MBExchange::sigterm(signo);
UniSetObject_LT::sigterm(signo);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void RTUExchange::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() )
{
std::cerr << 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 RTUExchange::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
{
if( UniSetTypes::check_filter(it,s_field,s_fvalue) )
initItem(it);
return true;
}
// ------------------------------------------------------------------------------------------
RTUExchange::RTUDevice* RTUExchange::addDev( RTUDeviceMap& mp, ModbusRTU::ModbusAddr a, UniXML_iterator& xmlit ) RTUExchange::RTUDevice* RTUExchange::addDev( RTUDeviceMap& mp, ModbusRTU::ModbusAddr a, UniXML_iterator& xmlit )
{ {
RTUDeviceMap::iterator it = mp.find(a); RTUDeviceMap::iterator it = mp.find(a);
...@@ -1223,24 +1089,6 @@ bool RTUExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, RTUExchange::RT ...@@ -1223,24 +1089,6 @@ bool RTUExchange::initRegInfo( RegInfo* r, UniXML_iterator& it, RTUExchange::RT
return true; return true;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
RTUExchange::DeviceType RTUExchange::getDeviceType( const std::string dtype )
{
if( dtype.empty() )
return dtUnknown;
if( dtype == "mtr" || dtype == "MTR" )
return dtMTR;
if( dtype == "rtu" || dtype == "RTU" )
return dtRTU;
if ( dtype == "rtu188" || dtype == "RTU188" )
return dtRTU188;
return dtUnknown;
}
// ------------------------------------------------------------------------------------------
bool RTUExchange::initRTUDevice( RTUDevice* d, UniXML_iterator& it ) bool RTUExchange::initRTUDevice( RTUDevice* d, UniXML_iterator& it )
{ {
d->dtype = getDeviceType(it.getProp("mbtype")); d->dtype = getDeviceType(it.getProp("mbtype"));
...@@ -1442,7 +1290,7 @@ bool RTUExchange::initRTU188item( UniXML_iterator& it, RegInfo* p ) ...@@ -1442,7 +1290,7 @@ bool RTUExchange::initRTU188item( UniXML_iterator& it, RegInfo* p )
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void RTUExchange::initIterators() void RTUExchange::initIterators()
{ {
shm->initAIterator(aitHeartBeat); MBExchange::initIterators();
for( RTUExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 ) for( RTUExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{ {
...@@ -1463,14 +1311,8 @@ void RTUExchange::initIterators() ...@@ -1463,14 +1311,8 @@ void RTUExchange::initIterators()
void RTUExchange::help_print( int argc, const char* const* argv ) void RTUExchange::help_print( int argc, const char* const* argv )
{ {
cout << "Default: prefix='rs'" << endl; cout << "Default: prefix='rs'" << endl;
cout << "--prefix-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек." << endl; MBExchange::help_print(argc,argv);
cout << "--prefix-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl; // cout << " Настройки протокола RS: " << endl;
cout << "--prefix-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--prefix-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--prefix-force - Сохранять значения в SM, независимо от, того менялось ли значение" << endl;
cout << "--prefix-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl;
cout << "--prefix-sm-ready-timeout - время на ожидание старта SM" << endl;
cout << " Настройки протокола RS: " << endl;
cout << "--prefix-dev devname - файл устройства" << endl; cout << "--prefix-dev devname - файл устройства" << endl;
cout << "--prefix-speed - Скорость обмена (9600,19920,38400,57600,115200)." << endl; cout << "--prefix-speed - Скорость обмена (9600,19920,38400,57600,115200)." << endl;
cout << "--prefix-my-addr - адрес текущего узла" << endl; cout << "--prefix-my-addr - адрес текущего узла" << endl;
...@@ -1500,30 +1342,6 @@ RTUExchange* RTUExchange::init_rtuexchange( int argc, const char* const* argv, U ...@@ -1500,30 +1342,6 @@ RTUExchange* RTUExchange::init_rtuexchange( int argc, const char* const* argv, U
return new RTUExchange(ID,icID,ic,prefix); return new RTUExchange(ID,icID,ic,prefix);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, const RTUExchange::DeviceType& dt )
{
switch(dt)
{
case RTUExchange::dtRTU:
os << "RTU";
break;
case RTUExchange::dtRTU188:
os << "RTU188";
break;
case RTUExchange::dtMTR:
os << "MTR";
break;
default:
os << "Unknown device type (" << (int)dt << ")";
break;
}
return os;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, const RTUExchange::RSProperty& p ) std::ostream& operator<<( std::ostream& os, const RTUExchange::RSProperty& p )
{ {
os << " (" << ModbusRTU::dat2str(p.reg->mbreg) << ")" os << " (" << ModbusRTU::dat2str(p.reg->mbreg) << ")"
...@@ -1750,6 +1568,9 @@ void RTUExchange::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -1750,6 +1568,9 @@ void RTUExchange::updateRSProperty( RSProperty* p, bool write_only )
if( !save && write_only ) if( !save && write_only )
return; return;
if( !checkUpdateSM(save) )
return;
try try
{ {
if( p->vType == VTypes::vtUnknown ) if( p->vType == VTypes::vtUnknown )
......
...@@ -5,22 +5,12 @@ ...@@ -5,22 +5,12 @@
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <vector>
#include "IONotifyController.h" #include "MBExchange.h"
#include "UniSetObject_LT.h"
#include "modbus/ModbusRTUMaster.h" #include "modbus/ModbusRTUMaster.h"
#include "PassiveTimer.h"
#include "Trigger.h"
#include "Mutex.h"
#include "Calibration.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "MTR.h"
#include "RTUStorage.h" #include "RTUStorage.h"
#include "IOBase.h"
#include "VTypes.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
class RTUExchange: class RTUExchange:
public UniSetObject_LT public MBExchange
{ {
public: public:
RTUExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, RTUExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID,
...@@ -35,24 +25,12 @@ class RTUExchange: ...@@ -35,24 +25,12 @@ class RTUExchange:
/*! глобальная функция для вывода help-а */ /*! глобальная функция для вывода help-а */
static void help_print( int argc, const char* const* argv ); static void help_print( int argc, const char* const* argv );
static const int NoSafetyState=-1;
enum Timer enum Timer
{ {
tmExchange tmExchange
}; };
enum DeviceType // --------------------------------------------------------
{
dtUnknown, /*!< неизвестный */
dtRTU, /*!< RTU (default) */
dtRTU188, /*!< RTU188 (Fastwell) */
dtMTR /*!< MTR (DEIF) */
};
static DeviceType getDeviceType( const std::string dtype );
friend std::ostream& operator<<( std::ostream& os, const DeviceType& dt );
// -------------------------------------------------------------------------------
struct RTUDevice; struct RTUDevice;
struct RegInfo; struct RegInfo;
...@@ -181,13 +159,7 @@ class RTUExchange: ...@@ -181,13 +159,7 @@ class RTUExchange:
bool use485F; bool use485F;
bool transmitCtl; bool transmitCtl;
xmlNode* cnode; virtual void step();
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void step();
void poll(); void poll();
bool pollRTU( RTUDevice* dev, RegMap::iterator& it ); bool pollRTU( RTUDevice* dev, RegMap::iterator& it );
...@@ -198,12 +170,11 @@ class RTUExchange: ...@@ -198,12 +170,11 @@ class RTUExchange:
void updateRSProperty( RSProperty* p, bool write_only=false ); void updateRSProperty( RSProperty* p, bool write_only=false );
virtual void processingMessage( UniSetTypes::VoidMessage *msg ); virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg ); virtual void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm ); virtual void sensorInfo( UniSetTypes::SensorMessage*sm );
void timerInfo( UniSetTypes::TimerMessage *tm ); void timerInfo( UniSetTypes::TimerMessage *tm );
void askSensors( UniversalIO::UIOCommand cmd ); void askSensors( UniversalIO::UIOCommand cmd );
void initOutput(); void initOutput();
void waitSMReady();
virtual bool activateObject(); virtual bool activateObject();
...@@ -211,13 +182,11 @@ class RTUExchange: ...@@ -211,13 +182,11 @@ class RTUExchange:
virtual void sigterm( int signo ); virtual void sigterm( int signo );
void initMB( bool reopen=false ); void initMB( bool reopen=false );
void initIterators(); virtual void initIterators();
bool initItem( UniXML_iterator& it ); bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
void initDeviceList(); void initDeviceList();
void initOffsetList(); void initOffsetList();
RTUDevice* addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML_iterator& it ); RTUDevice* addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML_iterator& it );
RegInfo* addReg( RegMap& rmap, ModbusRTU::ModbusData r, UniXML_iterator& it, RegInfo* addReg( RegMap& rmap, ModbusRTU::ModbusData r, UniXML_iterator& it,
RTUDevice* dev, RegInfo* rcopy=0 ); RTUDevice* dev, RegInfo* rcopy=0 );
...@@ -232,38 +201,14 @@ class RTUExchange: ...@@ -232,38 +201,14 @@ class RTUExchange:
void rtuQueryOptimization( RTUDeviceMap& m ); void rtuQueryOptimization( RTUDeviceMap& m );
void readConfiguration();
private: private:
RTUExchange(); RTUExchange();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
bool force; /*!< флаг означающий, что надо сохранять в SM, даже если значение не менялось */
bool force_out; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID;
int polltime; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_usec;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
UniSetTypes::uniset_mutex pollMutex; UniSetTypes::uniset_mutex pollMutex;
bool activated;
int activateTimeout;
bool rs_pre_clean; bool rs_pre_clean;
bool noQueryOptimization;
bool allNotRespond; bool allNotRespond;
Trigger trAllNotRespond; Trigger trAllNotRespond;
PassiveTimer ptAllNotRespond; PassiveTimer ptAllNotRespond;
std::string prefix;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#endif // _RS_EXCHANGE_H_ #endif // _RS_EXCHANGE_H_
......
#ifndef _MBExchange_H_
#define _MBExchange_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <map>
#include <vector>
#include "IONotifyController.h"
#include "UniSetObject_LT.h"
#include "PassiveTimer.h"
#include "Trigger.h"
#include "Mutex.h"
#include "Calibration.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "IOBase.h"
#include "VTypes.h"
#include "MTR.h"
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
/*!
\par Базовый класс для реализация обмена по протоколу Modbus [RTU|TCP].
*/
class MBExchange:
public UniSetObject_LT
{
public:
MBExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0,
const std::string prefix="mb" );
virtual ~MBExchange();
/*! глобальная функция для вывода help-а */
static void help_print( int argc, const char* const* argv );
static const int NoSafetyState=-1;
/*! Режимы работы процесса обмена */
enum ExchangeMode
{
emNone, /*!< нормальная работа (по умолчанию) */
emWriteOnly, /*!< "только посылка данных" (работают только write-функции) */
emReadOnly, /*!< "только чтение" (работают только read-функции) */
emSkipSaveToSM /*!< не писать данные в SM (при этом работают и read и write функции */
};
friend std::ostream& operator<<( std::ostream& os, const ExchangeMode& em );
enum DeviceType
{
dtUnknown, /*!< неизвестный */
dtRTU, /*!< RTU (default) */
dtMTR, /*!< MTR (DEIF) */
dtRTU188 /*!< RTU188 (Fastwell) */
};
static DeviceType getDeviceType( const std::string dtype );
friend std::ostream& operator<<( std::ostream& os, const DeviceType& dt );
protected:
virtual void step();
virtual void sensorInfo( UniSetTypes::SensorMessage* sm );
virtual void sigterm( int signo );
virtual bool initItem( UniXML_iterator& it ){ return false; }
virtual void initIterators();
bool checkUpdateSM( bool wrFunc );
bool checkPoll( bool wrFunc );
bool checkProcActive();
void setProcActive( bool st );
void waitSMReady();
void readConfiguration();
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
bool force; /*!< флаг означающий, что надо сохранять в SM, даже если значение не менялось */
bool force_out; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID;
int polltime; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_usec;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
UniSetTypes::ObjectId sidExchangeMode; /*!< иденидентификатор для датчика режима работы */
IOController::AIOStateList::iterator aitExchangeMode;
long exchangeMode; /*!< режим работы см. ExchangeMode */
UniSetTypes::uniset_mutex actMutex;
bool activated;
int activateTimeout;
bool noQueryOptimization;
std::string prefix;
timeout_t stat_time; /*!< время сбора статистики обмена */
int poll_count;
PassiveTimer ptStatistic; /*!< таймер для сбора статистики обмена */
private:
MBExchange();
};
// -----------------------------------------------------------------------------
#endif // _MBExchange_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),
shm(0),
initPause(0),
force(false),
force_out(false),
mbregFromID(false),
sidExchangeMode(DefaultObjectId),
activated(false),
noQueryOptimization(false),
prefix(prefix)
{
// 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 (имя) процесса. По умолчанию: MBTCPMaster1" << 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::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;
}
}
// ------------------------------------------------------------------------------------------
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);
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, const MBExchange::DeviceType& dt )
{
switch(dt)
{
case MBExchange::dtRTU:
os << "RTU";
break;
case MBExchange::dtMTR:
os << "MTR";
break;
default:
os << "Unknown device type (" << (int)dt << ")";
break;
}
return os;
}
// -----------------------------------------------------------------------------
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;
}
// -----------------------------------------------------------------------------
...@@ -6,6 +6,6 @@ libUniSetExtensions_la_LDFLAGS = -version-info $(UEXT_VER) ...@@ -6,6 +6,6 @@ libUniSetExtensions_la_LDFLAGS = -version-info $(UEXT_VER)
libUniSetExtensions_la_CPPFLAGS = $(SIGC_CFLAGS) -I$(top_builddir)/extensions/include libUniSetExtensions_la_CPPFLAGS = $(SIGC_CFLAGS) -I$(top_builddir)/extensions/include
libUniSetExtensions_la_LIBADD = $(SIGC_LIBS) $(top_builddir)/lib/libUniSet.la libUniSetExtensions_la_LIBADD = $(SIGC_LIBS) $(top_builddir)/lib/libUniSet.la
libUniSetExtensions_la_SOURCES = Extensions.cc SMInterface.cc Calibration.cc SingleProcess.cc \ libUniSetExtensions_la_SOURCES = Extensions.cc SMInterface.cc Calibration.cc SingleProcess.cc \
IOBase.cc DigitalFilter.cc PID.cc MTR.cc VTypes.cc IOBase.cc DigitalFilter.cc PID.cc MTR.cc VTypes.cc MBExchange.cc
#UObject_SK.cc #UObject_SK.cc
\ No newline at end of file
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