Commit 87abb2e8 authored by Pavel Vainerman's avatar Pavel Vainerman

Рефакторинг класса ModbusTCPMaster (и всех кто его использует).

Функции connect() теперь noexcept. P.S. (UNetUDP): чуть подправил тест
parent 46dae9ad
......@@ -144,7 +144,6 @@ int main( int argc, char** argv )
mb.setTimeout(tout);
mb.connect(iaddr, port);
mb.setForceDisconnect(!persist);
if( verb )
......
......@@ -332,13 +332,11 @@ int main( int argc, char** argv )
mb.setTimeout(tout);
mb.connect(iaddr, port);
mb.setForceDisconnect(!persist);
if( verb )
cout << "connection: " << (mb.isConnection() ? "YES" : "NO") << endl;
if( count > ModbusRTU::MAXDATALEN && verb )
cout << "Too long packet! Max count=" << ModbusRTU::MAXDATALEN << " (ignore...)" << endl;
......
......@@ -14,7 +14,7 @@
Name: libuniset2
Version: 2.5
Release: alt13
Release: alt14
Summary: UniSet - library for building distributed industrial control systems
License: LGPL
......@@ -486,6 +486,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# ..
%changelog
* Sun Sep 11 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt14
- (ModbusTCPMster): refactoring
* Fri Sep 09 2016 Pavel Vainerman <pv@altlinux.ru> 2.5-alt13
- minor fixes in millisecToPoco() and microsecToPoco() functions
......
......@@ -17,7 +17,6 @@
#include <cmath>
#include <limits>
#include <sstream>
#include <Poco/Net/NetException.h>
#include <Exceptions.h>
#include <extensions/Extensions.h>
#include "MBTCPMaster.h"
......@@ -95,15 +94,17 @@ std::shared_ptr<ModbusClient> MBTCPMaster::initMB( bool reopen )
if( !reopen )
return mbtcp;
mbtcp.reset();
mb.reset();
ptInitChannel.reset();
mbtcp->forceDisconnect();
mbtcp->connect(iaddr, port);
mbinfo << myname << "(init): ipaddr=" << iaddr << " port=" << port
<< " connection=" << (mbtcp->isConnection() ? "OK" : "FAIL" ) << endl;
mb = mbtcp;
return mbtcp;
}
try
{
mbtcp = std::make_shared<ModbusTCPMaster>();
mbtcp->connect(iaddr, port);
mbtcp->setForceDisconnect(force_disconnect);
......@@ -113,31 +114,14 @@ std::shared_ptr<ModbusClient> MBTCPMaster::initMB( bool reopen )
mbtcp->setSleepPause(sleepPause_msec);
mbtcp->setAfterSendPause(aftersend_pause);
mbinfo << myname << "(init): ipaddr=" << iaddr << " port=" << port << endl;
mbinfo << myname << "(init): ipaddr=" << iaddr << " port=" << port
<< " connection=" << (mbtcp->isConnection() ? "OK" : "FAIL" ) << endl;
auto l = loga->create(myname + "-exchangelog");
mbtcp->setLog(l);
if( ic )
ic->logAgregator()->add(loga);
}
catch( ModbusRTU::mbException& ex )
{
mbwarn << "(init): " << ex << endl;
mb = nullptr;
mbtcp = nullptr;
}
catch( const Poco::Net::NetException& e )
{
mbwarn << myname << "(init): Can`t create socket " << iaddr << ":" << port << " err: " << e.displayText() << endl;
mb = nullptr;
mbtcp = nullptr;
}
catch(...)
{
mb = nullptr;
mbtcp = nullptr;
}
mb = mbtcp;
return mbtcp;
......
......@@ -18,7 +18,6 @@
#include <limits>
#include <iomanip>
#include <sstream>
#include <Poco/Net/NetException.h>
#include <Exceptions.h>
#include <extensions/Extensions.h>
#include "MBTCPMultiMaster.h"
......@@ -315,46 +314,23 @@ bool MBTCPMultiMaster::MBSlaveInfo::check() const
// -----------------------------------------------------------------------------
bool MBTCPMultiMaster::MBSlaveInfo::init( std::shared_ptr<DebugStream>& mblog )
{
try
{
mbinfo << myname << "(init): connect..." << endl;
if( initOK )
return mbtcp->connect(ip, port);
mbtcp->connect(ip, port);
mbtcp->setForceDisconnect(force_disconnect);
if( recv_timeout > 0 )
mbtcp->setTimeout(recv_timeout);
// if( !initOK )
{
mbtcp->setSleepPause(sleepPause_usec);
mbtcp->setAfterSendPause(aftersend_pause);
if( mbtcp->isConnection() )
mbinfo << "(init): " << myname << " connect OK" << endl;
mbinfo << myname << "(init): connect " << (mbtcp->isConnection() ? "OK" : "FAIL" ) << endl;
initOK = true;
}
mbinfo << myname << "(init): connect " << mbtcp->isConnection() << endl;
return mbtcp->isConnection();
}
catch( ModbusRTU::mbException& ex )
{
mbwarn << "(init): " << ex << endl;
}
catch( const Poco::Net::NetException& e )
{
mbwarn << myname << "(init): Can`t create socket " << ip << ":" << port << " err: " << e.displayText() << endl;
}
catch(...)
{
mbwarn << "(init): " << myname << " catch ..." << endl;
}
initOK = false;
return false;
return initOK;
}
// -----------------------------------------------------------------------------
void MBTCPMultiMaster::sysCommand( const UniSetTypes::SystemMessage* sm )
......
......@@ -84,6 +84,46 @@ static void InitTest()
}
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: reconnect", "[modbus][mbmaster][mbtcpmaster]")
{
InitTest();
ModbusTCPMaster mb;
mb.setTimeout(500);
// подключение к несуществующему адресу
REQUIRE_FALSE(mb.connect("dummyhost", 2048));
REQUIRE_FALSE(mb.isConnection());
// нормальное подключение
REQUIRE(mb.connect(iaddr,port));
REQUIRE(mb.isConnection());
// переподключение (при активном текущем)
REQUIRE(mb.reconnect());
REQUIRE(mb.isConnection());
// отключение
mb.disconnect();
REQUIRE_FALSE(mb.isConnection());
// переподключение после отключения
REQUIRE(mb.reconnect());
REQUIRE(mb.isConnection());
// переподключение к несуществующему (при наличии активного подключения)
REQUIRE_FALSE(mb.connect("dummyhost", 2048));
REQUIRE_FALSE(mb.isConnection());
// нормальное подключение
REQUIRE(mb.connect(iaddr,port));
REQUIRE(mb.isConnection());
// принудительное отключение
mb.forceDisconnect();
REQUIRE_FALSE(mb.isConnection());
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: 0x01 (read coil status)", "[modbus][0x01][mbmaster][mbtcpmaster]")
{
InitTest();
......
......@@ -36,7 +36,7 @@ static void InitTest()
{
mb = std::make_shared<ModbusTCPMaster>();
mb->setTimeout(2000);
REQUIRE_NOTHROW( mb->connect(addr, port) );
mb->connect(addr, port);
msleep(5000);
}
}
......
......@@ -370,7 +370,10 @@ TEST_CASE("[UNetUDP]: check packets 'hole'", "[unetudp][udphole]")
// возвращаем к нормальному..чтобы следующие тесты не поломались..
for( int i = 0; i < 10; i++ )
{
send(pack2);
msleep(100);
}
}
// -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: check packets 'MaxDifferens'", "[unetudp][maxdifferens]")
......@@ -409,7 +412,7 @@ TEST_CASE("[UNetUDP]: bad packet number", "[unetudp][badnumber]")
UniSetUDP::UDPMessage pack;
pack.addAData(8, 60);
send(pack);
msleep(120);
msleep(150);
REQUIRE( ui->getValue(8) == 60 );
int lastpack = s_numpack - 1;
......
......@@ -18,8 +18,9 @@ class ModbusTCPMaster:
ModbusTCPMaster();
virtual ~ModbusTCPMaster();
void connect( const std::string& addr, int port );
void connect( const Poco::Net::SocketAddress& addr, int _port );
bool connect( const std::string& addr, int port, bool closeOldConnection=true ) noexcept;
bool connect( const Poco::Net::SocketAddress& addr, int _port, bool closeOldConnection=true ) noexcept;
void disconnect();
void forceDisconnect();
bool isConnection() const;
......@@ -31,7 +32,7 @@ class ModbusTCPMaster:
force_disconnect = s;
}
void reconnect();
bool reconnect();
void cleanInputStream();
virtual void cleanupChannel() override
......
......@@ -103,20 +103,10 @@ void UModbus::connect( const string& _ip, int _port )throw(UException)
ip = _ip;
port = _port;
try
{
mb->connect(ip, port);
}
catch( ModbusRTU::mbException& ex )
{
std::ostringstream err;
err << ex;
throw UException(err.str());
}
catch(...)
if( !mb->connect(ip, port) )
{
std::ostringstream err;
err << "Connection failed: ip=" << ip << " port=" << port;
err << "failed to connection ip=" << ip << " port=" << port;
throw UException(err.str());
}
}
......
......@@ -44,7 +44,6 @@ ModbusClient::~ModbusClient()
// -------------------------------------------------------------------------
void ModbusClient::setTimeout( timeout_t msec )
{
if( msec != UniSetTimer::WaitUpTime )
replyTimeOut_ms = msec;
}
// -------------------------------------------------------------------------
......
......@@ -63,7 +63,7 @@ void ModbusServer::setRecvTimeout( timeout_t msec )
timeout_t ModbusServer::setReplyTimeout( timeout_t msec )
{
// #warning "Why msec can be 0?"
assert(msec);
assert(msec>0);
if( msec == UniSetTimer::WaitUpTime )
return replyTimeout_ms;
......
......@@ -44,8 +44,6 @@ ModbusTCPMaster::~ModbusTCPMaster()
{
if( isConnection() )
disconnect();
tcp.reset();
}
// -------------------------------------------------------------------------
size_t ModbusTCPMaster::getNextData( unsigned char* buf, size_t len )
......@@ -81,7 +79,7 @@ mbErrCode ModbusTCPMaster::sendData( unsigned char* buf, size_t len )
}
// -------------------------------------------------------------------------
mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
ModbusMessage& reply, timeout_t timeout )
ModbusMessage& reply, timeout_t timeout_msec )
{
try
{
......@@ -109,15 +107,15 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
return erTimeOut;
}
assert(timeout);
ptTimeout.setTiming(timeout);
assert(timeout_msec);
ptTimeout.setTiming(timeout_msec);
tcp->setReceiveTimeout( UniSetTimer::millisecToPoco(timeout) );
tcp->setReceiveTimeout( UniSetTimer::millisecToPoco(timeout_msec) );
msg.makeHead(++nTransaction, crcNoCheckit);
for( size_t i = 0; i < 2; i++ )
{
if( tcp->poll(UniSetTimer::millisecToPoco(timeout), Poco::Net::Socket::SELECT_WRITE) )
if( tcp->poll(UniSetTimer::millisecToPoco(timeout_msec), Poco::Net::Socket::SELECT_WRITE) )
{
mbErrCode res = send(msg);
......@@ -146,14 +144,14 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
dlog->info() << "(ModbusTCPMaster::query): no write pending.. reconnnect OK" << endl;
}
if( timeout != UniSetTimer::WaitUpTime )
if( timeout_msec != UniSetTimer::WaitUpTime )
{
timeout = ptTimeout.getLeft(timeout);
timeout_msec = ptTimeout.getLeft(timeout_msec);
if( timeout == 0 )
if( timeout_msec == 0 )
return erTimeOut;
ptTimeout.setTiming(timeout);
ptTimeout.setTiming(timeout_msec);
}
// чистим очередь
......@@ -163,7 +161,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
//tcp->sync();
if( tcp->poll(UniSetTimer::millisecToPoco(timeout), Poco::Net::Socket::SELECT_READ ) )
if( tcp->poll(UniSetTimer::millisecToPoco(timeout_msec), Poco::Net::Socket::SELECT_READ ) )
{
size_t ret = 0;
......@@ -232,9 +230,9 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
}
//
timeout = ptTimeout.getLeft(timeout);
timeout_msec = ptTimeout.getLeft(timeout_msec);
if( timeout <= 0 )
if( timeout_msec <= 0 )
{
if( dlog->is_warn() )
......@@ -244,7 +242,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
}
//msg.aduhead = reply.aduhead;
mbErrCode res = recv(addr, msg.func(), reply, timeout);
mbErrCode res = recv(addr, msg.func(), reply, timeout_msec);
if( force_disconnect )
{
......@@ -261,7 +259,7 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
}
if( dlog->is_info() )
dlog->info() << "(query): input pending timeout=" << timeout << endl;
dlog->info() << "(query): input pending timeout=" << timeout_msec << endl;
if( force_disconnect )
{
......@@ -360,7 +358,7 @@ bool ModbusTCPMaster::checkConnection( const std::string& ip, int port, int time
return false;
}
// -------------------------------------------------------------------------
void ModbusTCPMaster::reconnect()
bool ModbusTCPMaster::reconnect()
{
if( dlog->is_info() )
dlog->info() << "(ModbusTCPMaster): reconnect " << iaddr << ":" << port << endl;
......@@ -368,50 +366,48 @@ void ModbusTCPMaster::reconnect()
if( tcp )
{
tcp->forceDisconnect();
tcp.reset();
tcp = nullptr;
}
return connect(iaddr, port, true);
}
// -------------------------------------------------------------------------
bool ModbusTCPMaster::connect( const std::string& addr, int _port, bool closeOldConnection ) noexcept
{
try
{
tcp = make_shared<UTCPStream>();
tcp->create(iaddr, port, 500);
tcp->setReceiveTimeout(UniSetTimer::millisecToPoco(replyTimeOut_ms));
tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms / 1000 : 1));
tcp->setNoDelay(true);
Net::SocketAddress sa(addr, _port);
return connect(sa, _port, closeOldConnection);
}
catch( const std::exception& e )
{
if( dlog->debugging(Debug::CRIT) )
{
ostringstream s;
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << s.str() << std::endl;
s << "(ModbusTCPMaster): connect " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << iaddr << std::endl;
}
}
catch( ... )
{
if( dlog->debugging(Debug::CRIT) )
if( closeOldConnection && tcp )
{
ostringstream s;
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: catch ...";
dlog->crit() << s.str() << std::endl;
}
forceDisconnect();
tcp = nullptr;
}
return false;
}
// -------------------------------------------------------------------------
void ModbusTCPMaster::connect( const std::string& addr, int _port )
{
Net::SocketAddress sa(addr, _port);
connect(sa, _port);
}
// -------------------------------------------------------------------------
void ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port )
bool ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port, bool closeOldConnection ) noexcept
{
if( tcp )
{
if( !closeOldConnection )
return false;
//disconnect();
forceDisconnect();
tcp.reset();
tcp = nullptr;
}
iaddr = addr.host().toString();
......@@ -428,6 +424,7 @@ void ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port )
tcp->setReceiveTimeout(UniSetTimer::millisecToPoco(replyTimeOut_ms));
tcp->setKeepAlive(true); // tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms / 1000 : 1));
tcp->setNoDelay(true);
return true;
}
catch( Poco::Net::NetException& ex)
{
......@@ -437,8 +434,6 @@ void ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port )
s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " error: " << ex.displayText();
dlog->crit() << iaddr << std::endl;
}
tcp = nullptr;
}
catch( const std::exception& e )
{
......@@ -448,8 +443,6 @@ void ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port )
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << iaddr << std::endl;
}
tcp = nullptr;
}
catch( ... )
{
......@@ -459,9 +452,10 @@ void ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port )
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: catch ...";
dlog->crit() << s.str() << std::endl;
}
}
tcp = nullptr;
}
return false;
}
// -------------------------------------------------------------------------
void ModbusTCPMaster::disconnect()
......@@ -473,7 +467,7 @@ void ModbusTCPMaster::disconnect()
return;
tcp->close();
tcp.reset();
tcp = nullptr;
}
// -------------------------------------------------------------------------
void ModbusTCPMaster::forceDisconnect()
......
......@@ -63,12 +63,9 @@ void LogReader::connect( const std::string& _addr, int _port, timeout_t msec )
if( tcp )
{
disconnect();
tcp = 0;
tcp = nullptr;
}
// if( !tcp )
// {
iaddr = _addr;
port = _port;
......@@ -83,6 +80,7 @@ void LogReader::connect( const std::string& _addr, int _port, timeout_t msec )
tcp->setSendTimeout( UniSetTimer::millisecToPoco(outTimeout) );
tcp->setKeepAlive(true);
tcp->setBlocking(true);
return;
}
catch( const Poco::TimeoutException& e )
{
......@@ -92,8 +90,6 @@ void LogReader::connect( const std::string& _addr, int _port, timeout_t msec )
s << "(LogReader): connection " << s.str() << " timeout..";
rlog.crit() << s.str() << std::endl;
}
tcp = 0;
}
catch( const Poco::Net::NetException& e )
{
......@@ -103,8 +99,6 @@ void LogReader::connect( const std::string& _addr, int _port, timeout_t msec )
s << "(LogReader): connection " << s.str() << " error: " << e.what();
rlog.crit() << s.str() << std::endl;
}
tcp = 0;
}
catch( const std::exception& e )
{
......@@ -114,8 +108,6 @@ void LogReader::connect( const std::string& _addr, int _port, timeout_t msec )
s << "(LogReader): connection " << s.str() << " error: " << e.what();
rlog.crit() << s.str() << std::endl;
}
tcp = 0;
}
catch( ... )
{
......@@ -127,7 +119,7 @@ void LogReader::connect( const std::string& _addr, int _port, timeout_t msec )
}
}
// }
tcp = nullptr;
}
// -------------------------------------------------------------------------
void LogReader::disconnect()
......@@ -148,7 +140,7 @@ void LogReader::disconnect()
cerr << "(LogReader): disconnect error: " << e.displayText() << endl;
}
tcp = 0;
tcp = nullptr;
}
// -------------------------------------------------------------------------
bool LogReader::isConnection() const
......
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