Commit c12314b3 authored by Pavel Vainerman's avatar Pavel Vainerman

(MBTCPMaster): встроил возможность переключения режима работы процесса

(только чтение, только запись и т.п.)
parent c7dbb803
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
<DumpStateTime name="10"/> <DumpStateTime name="10"/>
<SleepTickMS name="500"/> <SleepTickMS name="500"/>
<UniSetDebug levels="crit,warn" name="unideb"/> <UniSetDebug levels="crit,warn" name="unideb"/>
<ConfDir/> <ConfDir name="./" />
<DataDir/> <DataDir name="./" />
<BinDir/> <BinDir name="./" />
<LogDir/> <LogDir name="./" />
<DocDir/> <DocDir name="./" />
<LockDir/> <LockDir name="./" />
<Services> <Services>
<LocalTimeService AskLifeTimeSEC="10" MaxCountTimers="100" name="TimeService"/> <LocalTimeService AskLifeTimeSEC="10" MaxCountTimers="100" name="TimeService"/>
<LocalInfoServer dbrepeat="1" name="InfoServer"> <LocalInfoServer dbrepeat="1" name="InfoServer">
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
<sensors name="Sensors"> <sensors name="Sensors">
<item db_ignore="1" default="1" iotype="DI" name="Input1_S" priority="Medium" textname="Команда 1"/> <item db_ignore="1" default="1" iotype="DI" name="Input1_S" priority="Medium" textname="Команда 1"/>
<item iotype="DI" mbaddr="0x01" mbfunc="0x04" mbreg="0x02" mbtype="rtu" name="Input2_S" priority="Medium" rs="2" textname="Команда 2"/> <item iotype="DI" mbaddr="0x01" mbfunc="0x04" mbreg="0x02" mbtype="rtu" name="Input2_S" priority="Medium" rs="2" textname="Команда 2"/>
<item iotype="DI" mbtcp="1" name="Input3_S" priority="Medium" tcp_mbaddr="0x02" tcp_mbfunc="0x06" tcp_mbreg="0x02" tcp_mbtype="rtu" tcp_preinit="1" textname="Команда 3"/> <item iotype="DI" mbtcp="1" name="Input3_S" priority="Medium" tcp_mbaddr="0x02" tcp_mbfunc="0x03" tcp_mbreg="0x02" tcp_mbtype="rtu" tcp_preinit="1" textname="Команда 3"/>
<item iotype="DI" mbaddr="0x02" mbfunc="0x04" mbreg="0x02" mbtype="rtu" name="Input4_S" priority="Medium" rs="2" textname="Команда 4"/> <item iotype="DI" mbaddr="0x02" mbfunc="0x04" mbreg="0x02" mbtype="rtu" name="Input4_S" priority="Medium" rs="2" textname="Команда 4"/>
<item iotype="DI" name="Input5_S" priority="Medium" textname="Команда 5" udp="2"/> <item iotype="DI" name="Input5_S" priority="Medium" textname="Команда 5" udp="2"/>
<item iotype="DI" name="Input6_S" priority="Medium" textname="Команда 6" udp="2"> <item iotype="DI" name="Input6_S" priority="Medium" textname="Команда 6" udp="2">
...@@ -144,6 +144,7 @@ ...@@ -144,6 +144,7 @@
<item name="performance1" precision="6" noprecision="1" textname="Производительность танка 1" iotype="AI" rs="mbmaster" tcp_vtype="I2" tcp_mbtype="rtu" <item name="performance1" precision="6" noprecision="1" textname="Производительность танка 1" iotype="AI" rs="mbmaster" tcp_vtype="I2" tcp_mbtype="rtu"
tcp_mbaddr="1" tcp_mbreg="43" tcp_mbfunc="0x04"/> tcp_mbaddr="1" tcp_mbreg="43" tcp_mbfunc="0x04"/>
<item iotype="DI" name="Message1" priority="Medium" textname="Текст сообщения 1"/> <item iotype="DI" name="Message1" priority="Medium" textname="Текст сообщения 1"/>
<item iotype="AI" name="MB1_Mode_AS" priority="Medium" textname="ModbusExchange Mode"/>
</sensors> </sensors>
<thresholds name="thresholds"> <thresholds name="thresholds">
<sensor iotype="AI" name="AI_AS"> <sensor iotype="AI" name="AI_AS">
......
...@@ -20,6 +20,7 @@ initPause(0), ...@@ -20,6 +20,7 @@ initPause(0),
force(false), force(false),
force_out(false), force_out(false),
mbregFromID(false), mbregFromID(false),
sidExchangeMode(DefaultObjectId),
activated(false), activated(false),
noQueryOptimization(false), noQueryOptimization(false),
force_disconnect(true), force_disconnect(true),
...@@ -134,15 +135,24 @@ pollThread(0) ...@@ -134,15 +135,24 @@ pollThread(0)
dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl; dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl;
activateTimeout = conf->getArgPInt("--" + prefix + "-activate-timeout", 20000); string emode = conf->getArgParam("--" + prefix + "-exchange-mode-id",it.getProp("exchangeModeID"));
if( !emode.empty() )
// initMB(false); {
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); printMap(rmap);
// abort();
poll_count = -1; poll_count = -1;
pollThread = new ThreadCreator<MBTCPMaster>(this, &MBTCPMaster::poll_thread); pollThread = new ThreadCreator<MBTCPMaster>(this, &MBTCPMaster::poll_thread);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -311,6 +321,12 @@ void MBTCPMaster::poll_thread() ...@@ -311,6 +321,12 @@ void MBTCPMaster::poll_thread()
{ {
try try
{ {
if( sidExchangeMode != DefaultObjectId && force_out )
exchangeMode = shm->localGetValue(aitExchangeMode,sidExchangeMode);
}
catch(...){}
try
{
poll(); poll();
} }
catch(...){} catch(...){}
...@@ -486,6 +502,21 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it ) ...@@ -486,6 +502,21 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
} }
} }
if( exchangeMode == emWriteOnly && !ModbusRTU::isWriteFunction(p->mbfunc) )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): skip.. mode='emWriteOnly'" << endl;
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 )
{ {
if( dlog.debugging(Debug::INFO) ) if( dlog.debugging(Debug::INFO) )
...@@ -1149,6 +1180,20 @@ void MBTCPMaster::askSensors( UniversalIO::UIOCommand cmd ) ...@@ -1149,6 +1180,20 @@ void MBTCPMaster::askSensors( UniversalIO::UIOCommand cmd )
if( force_out ) if( force_out )
return; 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( 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);
...@@ -1181,6 +1226,14 @@ void MBTCPMaster::sensorInfo( UniSetTypes::SensorMessage* sm ) ...@@ -1181,6 +1226,14 @@ void MBTCPMaster::sensorInfo( UniSetTypes::SensorMessage* sm )
if( force_out ) if( force_out )
return; 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( 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);
...@@ -1829,6 +1882,7 @@ bool MBTCPMaster::initMTRitem( UniXML_iterator& it, RegInfo* p ) ...@@ -1829,6 +1882,7 @@ bool MBTCPMaster::initMTRitem( UniXML_iterator& it, RegInfo* p )
void MBTCPMaster::initIterators() void MBTCPMaster::initIterators()
{ {
shm->initAIterator(aitHeartBeat); shm->initAIterator(aitHeartBeat);
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 )
{ {
...@@ -2133,6 +2187,30 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only ) ...@@ -2133,6 +2187,30 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
if( !save && write_only ) if( !save && write_only )
return; return;
if( save && exchangeMode == emReadOnly )
{
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;
}
if( save && exchangeMode == emSkipSaveToSM )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "updateP: sid=" << p->si.id
<< " skip... mode='emSkipSaveToSM' " << endl;
return;
}
// если требуется инициализация и она ещё не произведена, // если требуется инициализация и она ещё не произведена,
// то игнорируем // то игнорируем
if( save && !r->mb_initOK ) if( save && !r->mb_initOK )
...@@ -2447,6 +2525,30 @@ void MBTCPMaster::updateMTR( RegMap::iterator& rit ) ...@@ -2447,6 +2525,30 @@ void MBTCPMaster::updateMTR( RegMap::iterator& rit )
using namespace ModbusRTU; using namespace ModbusRTU;
bool save = isWriteFunction( r->mbfunc ); 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 ) for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it )
{ {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
- \ref sec_MBTCP_Comm - \ref sec_MBTCP_Comm
- \ref sec_MBTCP_Conf - \ref sec_MBTCP_Conf
- \ref sec_MBTCP_ConfList - \ref sec_MBTCP_ConfList
- \ref sec_MBTCP_ExchangeMode
\section sec_MBTCP_Comm Общее описание ModbusTCP master \section sec_MBTCP_Comm Общее описание ModbusTCP master
Класс реализует процесс обмена (опрос/запись) с RTU-устройствами, Класс реализует процесс обмена (опрос/запись) с RTU-устройствами,
...@@ -163,6 +164,20 @@ ...@@ -163,6 +164,20 @@
\warning Регистр должен быть уникальным. И может повторятся только если указан параметр \a nbit или \a nbyte. \warning Регистр должен быть уникальным. И может повторятся только если указан параметр \a nbit или \a nbyte.
\section sec_MBTCP_ExchangeMode Управление режимом работы MBTCPMaster
В MBTCPMaster заложена возможность управлять режимом работы процесса. Поддерживаются
следующие режимы:
- \b emNone - нормальная работа (по умолчанию)
- \b emWriteOnly - "только посылка данных" (работают только write-функции)
- \b emReadOnly - "только чтение" (работают только read-функции)
- \b emSkipSaveToSM - "не записывать данные в SM", это особый режим, похожий на \b emWriteOnly,
но отличие в том, что при этом режиме ведётся полноценый обмен (и read и write),
только реально данные не записываются в SharedMemory(SM).
Режимы переключаются при помощи датчика, который можно задать либо аргументом командной строки
\b --prefix-exchange-mode-id либо в конф. файле параметром \b echangeModeID="". Константы определяющие режимы объявлены в MBTCPMaster::ExchangeMode.
*/ */
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/*! /*!
...@@ -194,6 +209,15 @@ class MBTCPMaster: ...@@ -194,6 +209,15 @@ class MBTCPMaster:
static const int NoSafetyState=-1; static const int NoSafetyState=-1;
/*! Режимы работы процесса обмена */
enum ExchangeMode
{
emNone, /*!< нормальная работа (по умолчанию) */
emWriteOnly, /*!< "только посылка данных" (работают только write-функции) */
emReadOnly, /*!< "только чтение" (работают только read-функции) */
emSkipSaveToSM /*!< не писать данные в SM (при этом работают и read и write функции */
};
enum Timer enum Timer
{ {
tmExchange tmExchange
...@@ -428,6 +452,10 @@ class MBTCPMaster: ...@@ -428,6 +452,10 @@ class MBTCPMaster:
IOController::AIOStateList::iterator aitHeartBeat; IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id; UniSetTypes::ObjectId test_id;
UniSetTypes::ObjectId sidExchangeMode; /*!< иденидентификатор для датчика режима работы */
IOController::AIOStateList::iterator aitExchangeMode;
long exchangeMode; /*!< режим работы см. ExchangeMode */
UniSetTypes::uniset_mutex actMutex; UniSetTypes::uniset_mutex actMutex;
bool activated; bool activated;
int activateTimeout; int activateTimeout;
......
#!/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 \
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
--mbtcp-gateway-iaddr 127.0.0.1 \ --mbtcp-gateway-iaddr 127.0.0.1 \
--mbtcp-gateway-port 2048 \ --mbtcp-gateway-port 2048 \
--mbtcp-recv-timeout 5000 \ --mbtcp-recv-timeout 5000 \
--mbtcp-force-disconnect 1 --mbtcp-force-disconnect 1 \
--mbtcp-polltime 5000 \
--mbtcp-exchange-mode-id MB1_Mode_AS
#--mbtcp-filter-field mbtcp --mbtcp-filter-value 1 #--mbtcp-filter-field mbtcp --mbtcp-filter-value 1
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