Commit a405f36f authored by Pavel Vainerman's avatar Pavel Vainerman

(ModbusSlave): добавил поддержку ответов на запросы ко многим

адресам для одного ModbusSlave.
parent eff3d777
...@@ -15,9 +15,9 @@ using namespace std; ...@@ -15,9 +15,9 @@ using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
using namespace ModbusRTU; using namespace ModbusRTU;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
MBSlave::MBSlave( ModbusRTU::ModbusAddr addr, const std::string& dev, const std::string& speed, bool use485 ): MBSlave::MBSlave(const std::unordered_set<ModbusAddr>& _vaddr, const std::string& dev, const std::string& speed, bool use485 ):
rscomm(NULL), rscomm(NULL),
addr(addr), vaddr(_vaddr),
// prev(ModbusRTU::erNoError), // prev(ModbusRTU::erNoError),
// askCount(0), // askCount(0),
verbose(false), verbose(false),
...@@ -31,7 +31,7 @@ MBSlave::MBSlave( ModbusRTU::ModbusAddr addr, const std::string& dev, const std: ...@@ -31,7 +31,7 @@ MBSlave::MBSlave( ModbusRTU::ModbusAddr addr, const std::string& dev, const std:
if( verbose ) if( verbose )
cout << "(init): " cout << "(init): "
<< " addr=" << ModbusRTU::addr2str(addr) << " addr=" << ModbusServer::vaddr2str(vaddr)
<< " dev=" << dev << " dev=" << dev
<< " speed=" << speed; << " speed=" << speed;
...@@ -80,7 +80,7 @@ void MBSlave::execute() ...@@ -80,7 +80,7 @@ void MBSlave::execute()
// Работа... // Работа...
while(1) while(1)
{ {
ModbusRTU::mbErrCode res = rscomm->receive( addr, UniSetTimer::WaitUpTime ); ModbusRTU::mbErrCode res = rscomm->receive( vaddr, UniSetTimer::WaitUpTime );
#if 0 #if 0
// собираем статистику обмена // собираем статистику обмена
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define MBSlave_H_ #define MBSlave_H_
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
#include <map> #include <map>
#include <unordered_set>
#include <string> #include <string>
#include "modbus/ModbusRTUSlaveSlot.h" #include "modbus/ModbusRTUSlaveSlot.h"
...@@ -11,7 +12,7 @@ ...@@ -11,7 +12,7 @@
class MBSlave class MBSlave
{ {
public: public:
MBSlave( ModbusRTU::ModbusAddr addr, const std::string& dev, const std::string& speed, bool use485 = false ); MBSlave( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, const std::string& dev, const std::string& speed, bool use485 = false );
~MBSlave(); ~MBSlave();
inline void setVerbose( bool state ) inline void setVerbose( bool state )
...@@ -96,7 +97,7 @@ class MBSlave ...@@ -96,7 +97,7 @@ class MBSlave
/*! интерфейс ModbusRTUSlave для обмена по RS */ /*! интерфейс ModbusRTUSlave для обмена по RS */
ModbusRTUSlaveSlot* rscomm; ModbusRTUSlaveSlot* rscomm;
ModbusRTU::ModbusAddr addr; /*!< адрес данного узла */ std::unordered_set<ModbusRTU::ModbusAddr> vaddr; /*!< адреса на которые отвечаем */
bool verbose; bool verbose;
#if 0 #if 0
......
...@@ -15,9 +15,9 @@ using namespace std; ...@@ -15,9 +15,9 @@ using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
using namespace ModbusRTU; using namespace ModbusRTU;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
MBTCPServer::MBTCPServer( ModbusAddr myaddr, const string& inetaddr, int port, bool verb ): MBTCPServer::MBTCPServer(const std::unordered_set<ModbusAddr>& myaddr, const string& inetaddr, int port, bool verb ):
sslot(NULL), sslot(NULL),
addr(myaddr), vaddr(myaddr),
// prev(ModbusRTU::erNoError), // prev(ModbusRTU::erNoError),
// askCount(0), // askCount(0),
verbose(verb), verbose(verb),
...@@ -66,7 +66,7 @@ MBTCPServer::~MBTCPServer() ...@@ -66,7 +66,7 @@ MBTCPServer::~MBTCPServer()
delete sslot; delete sslot;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void MBTCPServer::setLog( std::shared_ptr<DebugStream> dlog ) void MBTCPServer::setLog(std::shared_ptr<DebugStream>& dlog )
{ {
if( sslot ) if( sslot )
sslot->setLog(dlog); sslot->setLog(dlog);
...@@ -77,7 +77,7 @@ void MBTCPServer::execute() ...@@ -77,7 +77,7 @@ void MBTCPServer::execute()
// Работа... // Работа...
while(1) while(1)
{ {
ModbusRTU::mbErrCode res = sslot->receive( addr, UniSetTimer::WaitUpTime ); ModbusRTU::mbErrCode res = sslot->receive( vaddr, UniSetTimer::WaitUpTime );
#if 0 #if 0
// собираем статистику обмена // собираем статистику обмена
......
#ifndef MBTCPServer_H_ #ifndef MBTCPServer_H_
#define MBTCPServer_H_ #define MBTCPServer_H_
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
//#include <map> #include <unordered_set>
#include <string> #include <string>
#include "modbus/ModbusTCPServerSlot.h" #include "modbus/ModbusTCPServerSlot.h"
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
class MBTCPServer class MBTCPServer
{ {
public: public:
MBTCPServer( ModbusRTU::ModbusAddr myaddr, const std::string& inetaddr, int port = 502, bool verbose = false ); MBTCPServer( const std::unordered_set<ModbusRTU::ModbusAddr>& myaddr, const std::string& inetaddr, int port = 502, bool verbose = false );
~MBTCPServer(); ~MBTCPServer();
inline void setVerbose( bool state ) inline void setVerbose( bool state )
...@@ -23,14 +23,8 @@ class MBTCPServer ...@@ -23,14 +23,8 @@ class MBTCPServer
replyVal = val; replyVal = val;
} }
inline void setIgnoreAddrMode( bool state )
{
if( sslot )
sslot->setIgnoreAddrMode(state);
}
void execute(); /*!< основной цикл работы */ void execute(); /*!< основной цикл работы */
void setLog( std::shared_ptr<DebugStream> dlog ); void setLog( std::shared_ptr<DebugStream>& dlog );
protected: protected:
// действия при завершении работы // действия при завершении работы
...@@ -93,7 +87,7 @@ class MBTCPServer ...@@ -93,7 +87,7 @@ class MBTCPServer
/*! интерфейс ModbusSlave для обмена по RS */ /*! интерфейс ModbusSlave для обмена по RS */
ModbusTCPServerSlot* sslot; ModbusTCPServerSlot* sslot;
ModbusRTU::ModbusAddr addr; /*!< адрес данного узла */ std::unordered_set<ModbusRTU::ModbusAddr> vaddr; /*!< адреса данного узла */
bool verbose; bool verbose;
long replyVal; long replyVal;
......
...@@ -106,7 +106,11 @@ int main( int argc, char** argv ) ...@@ -106,7 +106,11 @@ int main( int argc, char** argv )
dlog->addLevel( Debug::type(Debug::CRIT | Debug::WARN | Debug::INFO) ); dlog->addLevel( Debug::type(Debug::CRIT | Debug::WARN | Debug::INFO) );
} }
MBSlave mbs(myaddr, dev, speed, use485); /*! \todo Доделать возможность задавать много адресов для ответа */
std::unordered_set<ModbusRTU::ModbusAddr> vaddr;
vaddr.emplace(myaddr);
MBSlave mbs(vaddr, dev, speed, use485);
mbs.setLog(dlog); mbs.setLog(dlog);
mbs.setVerbose(verb); mbs.setVerbose(verb);
......
...@@ -21,11 +21,12 @@ static struct option longopts[] = ...@@ -21,11 +21,12 @@ static struct option longopts[] =
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static void print_help() static void print_help()
{ {
printf("-h|--help - this message\n"); printf("-h|--help - this message\n");
printf("[-t|--timeout] msec - Timeout. Default: 2000.\n"); printf("[-t|--timeout] msec - Timeout. Default: 2000.\n");
printf("[-v|--verbose] - Print all messages to stdout\n"); printf("[-v|--verbose] - Print all messages to stdout\n");
printf("[-d|--device] dev - use device dev. Default: /dev/ttyS0\n"); printf("[-d|--device] dev - use device dev. Default: /dev/ttyS0\n");
printf("[-a|--myaddr] addr - Modbus address for this slave. Default: 0x01.\n"); printf("[-a|--myaddr] addr1,addr2,... - Modbus address for this slave. Default: 0x01.\n");
printf(" myaddr=255 - Reply to all RTU-addresses.\n");
printf("[-s|--speed] speed - 9600,14400,19200,38400,57600,115200. Default: 38400.\n"); printf("[-s|--speed] speed - 9600,14400,19200,38400,57600,115200. Default: 38400.\n");
printf("[-v|--verbose] - Print all messages to stdout\n"); printf("[-v|--verbose] - Print all messages to stdout\n");
printf("[-g|--f485] - Use 485 Fastwel\n"); printf("[-g|--f485] - Use 485 Fastwel\n");
...@@ -40,7 +41,7 @@ int main( int argc, char** argv ) ...@@ -40,7 +41,7 @@ int main( int argc, char** argv )
int f485 = 0; int f485 = 0;
string dev("/dev/ttyS0"); string dev("/dev/ttyS0");
string speed("38400"); string speed("38400");
ModbusRTU::ModbusAddr myaddr = 0x01; std::string myaddr("0x01");
int tout = 2000; int tout = 2000;
DebugStream dlog; DebugStream dlog;
...@@ -68,7 +69,7 @@ int main( int argc, char** argv ) ...@@ -68,7 +69,7 @@ int main( int argc, char** argv )
break; break;
case 'a': case 'a':
myaddr = ModbusRTU::str2mbAddr(optarg); myaddr = string(optarg);
break; break;
case 'v': case 'v':
...@@ -86,10 +87,15 @@ int main( int argc, char** argv ) ...@@ -86,10 +87,15 @@ int main( int argc, char** argv )
} }
} }
auto avec = UniSetTypes::explode_str(myaddr,',');
std::unordered_set<ModbusRTU::ModbusAddr> vaddr;
for( const auto& a: avec )
vaddr.emplace( ModbusRTU::str2mbAddr(a) );
if( verb ) if( verb )
{ {
cout << "(init): dev=" << dev << " speed=" << speed cout << "(init): dev=" << dev << " speed=" << speed
<< " myaddr=" << ModbusRTU::addr2str(myaddr) << " myaddr=" << ModbusServer::vaddr2str(vaddr)
<< " timeout=" << tout << " msec " << " timeout=" << tout << " msec "
<< endl; << endl;
...@@ -110,20 +116,20 @@ int main( int argc, char** argv ) ...@@ -110,20 +116,20 @@ int main( int argc, char** argv )
return 1; return 1;
} }
MBSlave mbs(cp, myaddr, speed); MBSlave mbs(cp, vaddr, speed);
mbs.setLog(dlog); mbs.setLog(dlog);
mbs.setVerbose(verb); mbs.setVerbose(verb);
mbs.execute(); mbs.execute();
} }
else else
{ {
MBSlave mbs(myaddr, dev, speed); MBSlave mbs(vaddr, dev, speed);
mbs.setLog(dlog); mbs.setLog(dlog);
mbs.setVerbose(verb); mbs.setVerbose(verb);
mbs.execute(); mbs.execute();
} }
} }
catch( ModbusRTU::mbException& ex ) catch( const ModbusRTU::mbException& ex )
{ {
cerr << "(mbtester): " << ex << endl; cerr << "(mbtester): " << ex << endl;
} }
......
...@@ -15,7 +15,6 @@ static struct option longopts[] = ...@@ -15,7 +15,6 @@ static struct option longopts[] =
{ "verbose", no_argument, 0, 'v' }, { "verbose", no_argument, 0, 'v' },
{ "myaddr", required_argument, 0, 'a' }, { "myaddr", required_argument, 0, 'a' },
{ "port", required_argument, 0, 'p' }, { "port", required_argument, 0, 'p' },
{ "reply-all", no_argument, 0, 'r' },
{ "const-reply", required_argument, 0, 'c' }, { "const-reply", required_argument, 0, 'c' },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
...@@ -23,13 +22,13 @@ static struct option longopts[] = ...@@ -23,13 +22,13 @@ static struct option longopts[] =
static void print_help() static void print_help()
{ {
printf("Example: uniset-mbtcpserver-echo -i localhost -p 2049 -v \n"); printf("Example: uniset-mbtcpserver-echo -i localhost -p 2049 -v \n");
printf("-h|--help - this message\n"); printf("-h|--help - this message\n");
printf("[-v|--verbose] - Print all messages to stdout\n"); printf("[-v|--verbose] - Print all messages to stdout\n");
printf("[-i|--iaddr] ip - Server listen ip. Default 127.0.0.1\n"); printf("[-i|--iaddr] ip - Server listen ip. Default 127.0.0.1\n");
printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n"); printf("[-a|--myaddr] addr1,addr2,... - Modbus address for master. Default: 0x01.\n");
printf("[-r|--reply-all] - Reply to all RTU-addresses.\n"); printf(" myaddr=255 - Reply to all RTU-addresses.\n");
printf("[-p|--port] port - Server port. Default: 502.\n"); printf("[-p|--port] port - Server port. Default: 502.\n");
printf("[-c|--const-reply] val - Reply 'val' for all queries\n"); printf("[-c|--const-reply] val - Reply 'val' for all queries\n");
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
int main( int argc, char** argv ) int main( int argc, char** argv )
...@@ -40,16 +39,15 @@ int main( int argc, char** argv ) ...@@ -40,16 +39,15 @@ int main( int argc, char** argv )
int verb = 0; int verb = 0;
int port = 502; int port = 502;
string iaddr("127.0.0.1"); string iaddr("127.0.0.1");
ModbusRTU::ModbusAddr myaddr = 0x01; string myaddr("0x01");
auto dlog = make_shared<DebugStream>(); auto dlog = make_shared<DebugStream>();
bool ignoreAddr = false;
int replyVal = -1; int replyVal = -1;
ost::Thread::setException(ost::Thread::throwException); ost::Thread::setException(ost::Thread::throwException);
try try
{ {
while( (opt = getopt_long(argc, argv, "hva:p:i:brc:", longopts, &optindex)) != -1 ) while( (opt = getopt_long(argc, argv, "hva:p:i:bc:", longopts, &optindex)) != -1 )
{ {
switch (opt) switch (opt)
{ {
...@@ -66,17 +64,13 @@ int main( int argc, char** argv ) ...@@ -66,17 +64,13 @@ int main( int argc, char** argv )
break; break;
case 'a': case 'a':
myaddr = ModbusRTU::str2mbAddr(optarg); myaddr = string(optarg);
break; break;
case 'v': case 'v':
verb = 1; verb = 1;
break; break;
case 'r':
ignoreAddr = true;
break;
case 'c': case 'c':
replyVal = uni_atoi(optarg); replyVal = uni_atoi(optarg);
break; break;
...@@ -88,19 +82,23 @@ int main( int argc, char** argv ) ...@@ -88,19 +82,23 @@ int main( int argc, char** argv )
} }
} }
auto avec = UniSetTypes::explode_str(myaddr,',');
std::unordered_set<ModbusRTU::ModbusAddr> vaddr;
for( const auto& a: avec )
vaddr.emplace( ModbusRTU::str2mbAddr(a) );
if( verb ) if( verb )
{ {
cout << "(init): iaddr: " << iaddr << ":" << port cout << "(init): iaddr: " << iaddr << ":" << port
<< " myaddr=" << ModbusRTU::addr2str(myaddr) << " myaddr=" << ModbusServer::vaddr2str(vaddr)
<< endl; << endl;
dlog->addLevel( Debug::ANY ); dlog->addLevel( Debug::ANY );
} }
MBTCPServer mbs(myaddr, iaddr, port, verb); MBTCPServer mbs(vaddr, iaddr, port, verb);
mbs.setLog(dlog); mbs.setLog(dlog);
mbs.setVerbose(verb); mbs.setVerbose(verb);
mbs.setIgnoreAddrMode(ignoreAddr);
if( replyVal != -1 ) if( replyVal != -1 )
mbs.setReply(replyVal); mbs.setReply(replyVal);
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
Name: libuniset2 Name: libuniset2
Version: 2.2 Version: 2.2
Release: alt4 Release: alt5
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
...@@ -456,6 +456,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname ...@@ -456,6 +456,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# .. # ..
%changelog %changelog
* Fri Oct 02 2015 Pavel Vainerman <pv@altlinux.ru> 2.2-alt5
- (ModbusSlave): added support for multiple addresses for MBSlave
* Fri Oct 02 2015 Pavel Vainerman <pv@altlinux.ru> 2.2-alt4 * Fri Oct 02 2015 Pavel Vainerman <pv@altlinux.ru> 2.2-alt4
- (ModbusSlave): added support setBroadcastMode() // addr = 255 - (ModbusSlave): added support setBroadcastMode() // addr = 255
- (codegen): change log for 'unknown message id' crit --> level8 - (codegen): change log for 'unknown message id' crit --> level8
......
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
</MBMultiSlave1> </MBMultiSlave1>
<MBSlave1 addr="0x31" aftersend-pause="0" dev="/dev/ttyS0" levels="info,warn,crit" name="MBSlave1" poll_time="200" reply_timeout="60" speed="9600"> <MBSlave1 aftersend-pause="0" dev="/dev/ttyS0" levels="info,warn,crit" name="MBSlave1" poll_time="200" reply_timeout="60" speed="9600">
<filelist> <filelist>
<!-- Список файлов разрешённых для передачи по modbus <!-- Список файлов разрешённых для передачи по modbus
directory - каталог где лежит файл. Можно не задавать directory - каталог где лежит файл. Можно не задавать
......
...@@ -18,9 +18,9 @@ std::ostream& operator<<(std::ostream& os, const MBTCPTestServer* m ) ...@@ -18,9 +18,9 @@ std::ostream& operator<<(std::ostream& os, const MBTCPTestServer* m )
return os << m->myname; return os << m->myname;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
MBTCPTestServer::MBTCPTestServer( ModbusAddr myaddr, const string& inetaddr, int port, bool verb ): MBTCPTestServer::MBTCPTestServer( const std::unordered_set<ModbusAddr>& _vaddr, const string& inetaddr, int port, bool verb ):
sslot(NULL), sslot(NULL),
addr(myaddr), vaddr(_vaddr),
verbose(verb), verbose(verb),
replyVal(-1), replyVal(-1),
forceSingleCoilCmd(false), forceSingleCoilCmd(false),
...@@ -51,13 +51,13 @@ MBTCPTestServer::MBTCPTestServer( ModbusAddr myaddr, const string& inetaddr, int ...@@ -51,13 +51,13 @@ MBTCPTestServer::MBTCPTestServer( ModbusAddr myaddr, const string& inetaddr, int
catch( const ost::SockException& e ) catch( const ost::SockException& e )
{ {
ostringstream err; ostringstream err;
err << "(MBTCPTestServer::init): Can`t create socket " << addr << ":" << port << " err: " << e.getString() << endl; err << "(MBTCPTestServer::init): Can`t create socket " << inetaddr << ":" << port << " err: " << e.getString() << endl;
cerr << err.str() << endl; cerr << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
cerr << "(MBTCPTestServer::init): Can`t create socket " << addr << ":" << port << " err: " << ex.what() << endl; cerr << "(MBTCPTestServer::init): Can`t create socket " << inetaddr << ":" << port << " err: " << ex.what() << endl;
throw; throw;
} }
...@@ -119,7 +119,7 @@ void MBTCPTestServer::execute() ...@@ -119,7 +119,7 @@ void MBTCPTestServer::execute()
// Работа... // Работа...
while(1) while(1)
{ {
ModbusRTU::mbErrCode res = sslot->receive( addr, UniSetTimer::WaitUpTime ); ModbusRTU::mbErrCode res = sslot->receive( vaddr, UniSetTimer::WaitUpTime );
#if 0 #if 0
// собираем статистику обмена // собираем статистику обмена
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <string> #include <string>
#include <atomic> #include <atomic>
#include <ostream> #include <ostream>
#include <unordered_set>
#include "ThreadCreator.h" #include "ThreadCreator.h"
#include "modbus/ModbusTCPServerSlot.h" #include "modbus/ModbusTCPServerSlot.h"
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -11,7 +12,7 @@ ...@@ -11,7 +12,7 @@
class MBTCPTestServer class MBTCPTestServer
{ {
public: public:
MBTCPTestServer( ModbusRTU::ModbusAddr myaddr, const std::string& inetaddr, int port = 502, bool verbose = false ); MBTCPTestServer( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, const std::string& inetaddr, int port = 502, bool verbose = false );
~MBTCPTestServer(); ~MBTCPTestServer();
inline void setVerbose( bool state ) inline void setVerbose( bool state )
...@@ -130,7 +131,7 @@ class MBTCPTestServer ...@@ -130,7 +131,7 @@ class MBTCPTestServer
/*! интерфейс ModbusSlave для обмена по RS */ /*! интерфейс ModbusSlave для обмена по RS */
ModbusTCPServerSlot* sslot; ModbusTCPServerSlot* sslot;
ModbusRTU::ModbusAddr addr; /*!< адрес данного узла */ std::unordered_set<ModbusRTU::ModbusAddr> vaddr; /*!< адреса данного узла */
bool verbose; bool verbose;
long replyVal; long replyVal;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <time.h> #include <time.h>
#include <memory> #include <memory>
#include <unordered_set>
#include <limits> #include <limits>
#include "UniSetTypes.h" #include "UniSetTypes.h"
#include "MBTCPTestServer.h" #include "MBTCPTestServer.h"
...@@ -12,8 +13,9 @@ using namespace UniSetTypes; ...@@ -12,8 +13,9 @@ using namespace UniSetTypes;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static ModbusRTU::ModbusAddr slaveaddr = 0x01; // conf->getArgInt("--mbs-my-addr"); static ModbusRTU::ModbusAddr slaveaddr = 0x01; // conf->getArgInt("--mbs-my-addr");
static int port = 20048; // conf->getArgInt("--mbs-inet-port"); static int port = 20048; // conf->getArgInt("--mbs-inet-port");
static string addr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr"); static string iaddr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr");
static ModbusRTU::ModbusAddr slaveADDR = 0x01; static const ModbusRTU::ModbusAddr slaveADDR = 0x01;
static unordered_set<ModbusRTU::ModbusAddr> vaddr = { slaveADDR };
static shared_ptr<MBTCPTestServer> mbs; static shared_ptr<MBTCPTestServer> mbs;
static shared_ptr<UInterface> ui; static shared_ptr<UInterface> ui;
static std::shared_ptr<SMInterface> smi; static std::shared_ptr<SMInterface> smi;
...@@ -53,18 +55,18 @@ static void InitTest() ...@@ -53,18 +55,18 @@ static void InitTest()
{ {
try try
{ {
mbs = make_shared<MBTCPTestServer>(slaveADDR, addr, port, false); mbs = make_shared<MBTCPTestServer>(vaddr, iaddr, port, false);
} }
catch( const ost::SockException& e ) catch( const ost::SockException& e )
{ {
ostringstream err; ostringstream err;
err << "(mbs): Can`t create socket " << addr << ":" << port << " err: " << e.getString() << endl; err << "(mbs): Can`t create socket " << iaddr << ":" << port << " err: " << e.getString() << endl;
cerr << err.str() << endl; cerr << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
cerr << "(mbs): Can`t create socket " << addr << ":" << port << " err: " << ex.what() << endl; cerr << "(mbs): Can`t create socket " << iaddr << ":" << port << " err: " << ex.what() << endl;
throw; throw;
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <time.h> #include <time.h>
#include <limits> #include <limits>
#include <unordered_set>
#include "UniSetTypes.h" #include "UniSetTypes.h"
#include "MBTCPMultiMaster.h" #include "MBTCPMultiMaster.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -22,10 +23,10 @@ using namespace UniSetTypes; ...@@ -22,10 +23,10 @@ using namespace UniSetTypes;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static ModbusRTU::ModbusAddr slaveaddr = 0x01; // conf->getArgInt("--mbs-my-addr"); static ModbusRTU::ModbusAddr slaveaddr = 0x01; // conf->getArgInt("--mbs-my-addr");
static int port = 20053; // conf->getArgInt("--mbs-inet-port"); static int port = 20053; // conf->getArgInt("--mbs-inet-port");
static string addr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr"); static string iaddr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr");
static int port2 = 20055; static int port2 = 20055;
static string addr2("127.0.0.1"); static string iaddr2("127.0.0.1");
static ModbusRTU::ModbusAddr slaveADDR = 0x01; static unordered_set<ModbusRTU::ModbusAddr> slaveADDR = { 0x01 };
static shared_ptr<MBTCPTestServer> mbs1; static shared_ptr<MBTCPTestServer> mbs1;
static shared_ptr<MBTCPTestServer> mbs2; static shared_ptr<MBTCPTestServer> mbs2;
static shared_ptr<UInterface> ui; static shared_ptr<UInterface> ui;
...@@ -55,18 +56,18 @@ static void InitTest() ...@@ -55,18 +56,18 @@ static void InitTest()
try try
{ {
ost::Thread::setException(ost::Thread::throwException); ost::Thread::setException(ost::Thread::throwException);
mbs1 = make_shared<MBTCPTestServer>(slaveADDR, addr, port, false); mbs1 = make_shared<MBTCPTestServer>(slaveADDR, iaddr, port, false);
} }
catch( const ost::SockException& e ) catch( const ost::SockException& e )
{ {
ostringstream err; ostringstream err;
err << "(mb1): Can`t create socket " << addr << ":" << port << " err: " << e.getString() << endl; err << "(mb1): Can`t create socket " << iaddr << ":" << port << " err: " << e.getString() << endl;
cerr << err.str() << endl; cerr << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
cerr << "(mb1): Can`t create socket " << addr << ":" << port << " err: " << ex.what() << endl; cerr << "(mb1): Can`t create socket " << iaddr << ":" << port << " err: " << ex.what() << endl;
throw; throw;
} }
...@@ -87,18 +88,18 @@ static void InitTest() ...@@ -87,18 +88,18 @@ static void InitTest()
try try
{ {
ost::Thread::setException(ost::Thread::throwException); ost::Thread::setException(ost::Thread::throwException);
mbs2 = make_shared<MBTCPTestServer>(slaveADDR, addr2, port2, false); mbs2 = make_shared<MBTCPTestServer>(slaveADDR, iaddr2, port2, false);
} }
catch( const ost::SockException& e ) catch( const ost::SockException& e )
{ {
ostringstream err; ostringstream err;
err << "(mb2): Can`t create socket " << addr << ":" << port << " err: " << e.getString() << endl; err << "(mb2): Can`t create socket " << iaddr << ":" << port << " err: " << e.getString() << endl;
cerr << err.str() << endl; cerr << err.str() << endl;
throw SystemError(err.str()); throw SystemError(err.str());
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
cerr << "(mb2): Can`t create socket " << addr << ":" << port << " err: " << ex.what() << endl; cerr << "(mb2): Can`t create socket " << iaddr << ":" << port << " err: " << ex.what() << endl;
throw; throw;
} }
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <condition_variable>
#include <atomic>
#include <mutex>
#include "UniSetObject_LT.h" #include "UniSetObject_LT.h"
#include "modbus/ModbusTypes.h" #include "modbus/ModbusTypes.h"
#include "modbus/ModbusServerSlot.h" #include "modbus/ModbusServerSlot.h"
...@@ -67,7 +70,7 @@ ...@@ -67,7 +70,7 @@
в которой указываются настроечные параметры по умолчанию. в которой указываются настроечные параметры по умолчанию.
Пример: Пример:
\code \code
<MBSlave1 name="MBSlave1" addr="0x31" <MBSlave1 name="MBSlave1" default_mbaddr="0x31"
afterSendPause="0" afterSendPause="0"
reg_from_id="0" reg_from_id="0"
replyTimeout="60" replyTimeout="60"
...@@ -81,7 +84,7 @@ ...@@ -81,7 +84,7 @@
... ...
\endcode \endcode
- \b addr - адрес данного устройства. Если указан адрес 255 - ответ будет на любые сообщения. - \b default_mbaddr - адрес по умолчанию для данного устройства. Если указан адрес 255 - ответ будет на любые сообщения.
- \b afterSendPause - принудительная пауза после посылки ответа - \b afterSendPause - принудительная пауза после посылки ответа
- \b reg_from_id - номер регистра брать из ID датчика - \b reg_from_id - номер регистра брать из ID датчика
- \b replyTimeout - таймаут на формирование ответа. Если ответ на запрос будет сформирован за большее время, он не будет отослан. - \b replyTimeout - таймаут на формирование ответа. Если ответ на запрос будет сформирован за большее время, он не будет отослан.
...@@ -118,9 +121,9 @@ ...@@ -118,9 +121,9 @@
\b --xxx-name ID - идентификатор процесса. \b --xxx-name ID - идентификатор процесса.
\b --xxx-my-addr addr - slave-адрес для данного устройства. Если указан адрес 255 - ответ будет на любые сообщения. \b --xxx-default-mbaddr addr1 - slave-адрес по умолчанию для данного устройства. Если указан адрес 255 - ответ будет на любые сообщения.
\b --xxx-timeout или \b timeout msec - таймаут на определение отсутсвия связи. \b --xxx-timeout или \b timeout msec - таймаут на определение отсутсвия связи.
\b --xxx-reply-timeout msec - таймаут на формирование ответа. \b --xxx-reply-timeout msec - таймаут на формирование ответа.
...@@ -175,8 +178,11 @@ ...@@ -175,8 +178,11 @@
<sensors name="Sensors"> <sensors name="Sensors">
... ...
<item name="MySensor_S" textname="my sesnsor" iotype="DI" <item name="MySensor_S" textname="my sesnsor" iotype="DI"
mbs="1" mbreg="1" mbs="1" mbs_mbaddr="0x02" mbs_mbreg="1"
/> />
<item name="MySensor2_S" textname="my sesnsor 2" iotype="DI"
mbs="1" mbs_mbaddr="0x01" mbs_mbreg="1"
/>
... ...
</sensors> </sensors>
\endcode \endcode
...@@ -184,6 +190,7 @@ ...@@ -184,6 +190,7 @@
\warning По умолчанию для свойств используется заданный в конструктроре префикс "mbs_". \warning По умолчанию для свойств используется заданный в конструктроре префикс "mbs_".
К основным параметрам настройки датчиков относятся следующие (префикс \b mbs_ - для примера): К основным параметрам настройки датчиков относятся следующие (префикс \b mbs_ - для примера):
- \b mbs_mbadrr - адрес к которому относиться данный регистр. Если не используется параметр \b default_mbaddr.
- \b mbs_mbreg - запрашиваемый/записываемый регистр. Если не используется параметр \b reg_from_id. - \b mbs_mbreg - запрашиваемый/записываемый регистр. Если не используется параметр \b reg_from_id.
Помимо этого можно задавать следующие параметры: Помимо этого можно задавать следующие параметры:
...@@ -430,11 +437,15 @@ class MBSlave: ...@@ -430,11 +437,15 @@ class MBSlave:
// т.к. в функциях (much_real_read,nuch_real_write) рассчёт на отсортированность IOMap // т.к. в функциях (much_real_read,nuch_real_write) рассчёт на отсортированность IOMap
// то использовать unordered_map нельзя // то использовать unordered_map нельзя
typedef std::map<ModbusRTU::RegID, IOProperty> IOMap; typedef std::map<ModbusRTU::RegID, IOProperty> RegMap;
IOMap iomap; /*!< список входов/выходов */
typedef std::unordered_map<ModbusRTU::ModbusAddr,RegMap> IOMap;
IOMap iomap; /*!< список входов/выходов по адресам */
std::shared_ptr<ModbusServerSlot> mbslot; std::shared_ptr<ModbusServerSlot> mbslot;
ModbusRTU::ModbusAddr addr = { 0x01 }; /*!< адрес данного узла */ std::unordered_set<ModbusRTU::ModbusAddr> vaddr; /*!< адреса данного узла */
std::string default_mbaddr;
xmlNode* cnode; xmlNode* cnode;
std::string s_field; std::string s_field;
...@@ -464,17 +475,17 @@ class MBSlave: ...@@ -464,17 +475,17 @@ class MBSlave:
void readConfiguration(); void readConfiguration();
bool check_item( UniXML::iterator& it ); bool check_item( UniXML::iterator& it );
ModbusRTU::mbErrCode real_write( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData val, const int fn = 0 ); ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData val, const int fn = 0 );
ModbusRTU::mbErrCode real_write( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int& i, int count, const int fn = 0 ); ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int& i, int count, const int fn = 0 );
ModbusRTU::mbErrCode real_read( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val, const int fn = 0 ); ModbusRTU::mbErrCode real_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val, const int fn = 0 );
ModbusRTU::mbErrCode much_real_read( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int count, const int fn = 0 ); ModbusRTU::mbErrCode much_real_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int count, const int fn = 0 );
ModbusRTU::mbErrCode much_real_write( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int count, const int fn = 0 ); ModbusRTU::mbErrCode much_real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int count, const int fn = 0 );
ModbusRTU::mbErrCode real_read_it( IOMap::iterator& it, ModbusRTU::ModbusData& val ); ModbusRTU::mbErrCode real_read_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData& val );
ModbusRTU::mbErrCode real_bitreg_read_it( std::shared_ptr<BitRegProperty>& bp, ModbusRTU::ModbusData& val ); ModbusRTU::mbErrCode real_bitreg_read_it( std::shared_ptr<BitRegProperty>& bp, ModbusRTU::ModbusData& val );
ModbusRTU::mbErrCode real_read_prop( IOProperty* p, ModbusRTU::ModbusData& val ); ModbusRTU::mbErrCode real_read_prop( IOProperty* p, ModbusRTU::ModbusData& val );
ModbusRTU::mbErrCode real_write_it( IOMap::iterator& it, ModbusRTU::ModbusData* dat, int& i, int count ); ModbusRTU::mbErrCode real_write_it(RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData* dat, int& i, int count );
ModbusRTU::mbErrCode real_bitreg_write_it( std::shared_ptr<BitRegProperty>& bp, const ModbusRTU::ModbusData val ); ModbusRTU::mbErrCode real_bitreg_write_it( std::shared_ptr<BitRegProperty>& bp, const ModbusRTU::ModbusData val );
ModbusRTU::mbErrCode real_write_prop( IOProperty* p, ModbusRTU::ModbusData* dat, int& i, int count ); ModbusRTU::mbErrCode real_write_prop( IOProperty* p, ModbusRTU::ModbusData* dat, int& i, int count );
...@@ -483,6 +494,9 @@ class MBSlave: ...@@ -483,6 +494,9 @@ class MBSlave:
UniSetTypes::uniset_rwmutex mutex_start; UniSetTypes::uniset_rwmutex mutex_start;
std::shared_ptr< ThreadCreator<MBSlave> > thr; std::shared_ptr< ThreadCreator<MBSlave> > thr;
std::mutex mutexStartNotify;
std::condition_variable startNotifyEvent;
PassiveTimer ptHeartBeat; PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat; UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat; int maxHeartBeat;
......
...@@ -173,11 +173,13 @@ void MBTCPPersistentSlave::execute_tcp() ...@@ -173,11 +173,13 @@ void MBTCPPersistentSlave::execute_tcp()
mbinfo << myname << "(execute_tcp): thread running.." << endl; mbinfo << myname << "(execute_tcp): thread running.." << endl;
while( !cancelled ) while( !cancelled )
{ {
try try
{ {
sslot->waitQuery( addr, waitTimeout ); sslot->waitQuery( vaddr, waitTimeout );
// если слишком быстро обработали запрос // если слишком быстро обработали запрос
// то ничего не делаем.. // то ничего не делаем..
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
</History> </History>
</SharedMemory> </SharedMemory>
<MBSlave1 addr="0x31" aftersend-pause="0" device="/dev/ttyS0" name="MBSlave1" poll_time="200" reply_timeout="60" speed="9600"> <MBSlave1 default_mbaddr="0x01" aftersend-pause="0" device="/dev/ttyS0" name="MBSlave1" poll_time="200" reply_timeout="60" speed="9600">
<filelist> <filelist>
<!-- Список файлов разрешённых для передачи по modbus <!-- Список файлов разрешённых для передачи по modbus
directory - каталог где лежит файл. Можно не задавать directory - каталог где лежит файл. Можно не задавать
...@@ -199,6 +199,9 @@ ...@@ -199,6 +199,9 @@
<item id="2050" mbs="1" mbreg="259" iotype="AO" vtype="F2" name="Test_CountWrite10_F2" textname="Тестовый регистр для 0x10(F2)"/> <item id="2050" mbs="1" mbreg="259" iotype="AO" vtype="F2" name="Test_CountWrite10_F2" textname="Тестовый регистр для 0x10(F2)"/>
<item id="2051" mbs="1" mbreg="261" iotype="AO" vtype="F2" precision="1" name="Test_CountWrite10_F2prec" textname="Тестовый регистр для 0x10(F2)(prec)"/> <item id="2051" mbs="1" mbreg="261" iotype="AO" vtype="F2" precision="1" name="Test_CountWrite10_F2prec" textname="Тестовый регистр для 0x10(F2)(prec)"/>
<item id="2053" mbs="1" mbaddr="0x02" mbreg="130" default="1" iotype="AO" name="Test_SlaveAddr2" textname="Тестовый регистр для проверки работы со вторым адресом (mbreg)"/>
<item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/> <item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/>
......
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static ModbusRTU::ModbusAddr slaveaddr = 0x01; // conf->getArgInt("--mbs-my-addr"); static ModbusRTU::ModbusAddr slaveaddr = 0x01;
static ModbusRTU::ModbusAddr slaveaddr2 = 0x02;
static int port = 20048; // conf->getArgInt("--mbs-inet-port"); static int port = 20048; // conf->getArgInt("--mbs-inet-port");
static string addr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr"); static string addr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr");
static ObjectId slaveID = 6004; // conf->getObjectID( conf->getArgParam("--mbs-name")); static ObjectId slaveID = 6004; // conf->getObjectID( conf->getArgParam("--mbs-name"));
...@@ -1179,4 +1180,19 @@ TEST_CASE("(0x10): write register outputs or memories [F2](precision)", "[modbus ...@@ -1179,4 +1180,19 @@ TEST_CASE("(0x10): write register outputs or memories [F2](precision)", "[modbus
REQUIRE( (float)r_f2 == 20.3f ); REQUIRE( (float)r_f2 == 20.3f );
} }
// ------------------------------------------------------------- // -------------------------------------------------------------
TEST_CASE("Multi adress check", "[modbus][mbslave][multiaddress]")
{
using namespace VTypes;
InitTest();
ModbusRTU::ModbusData tREG = 130;
int num = 10;
ModbusRTU::ReadOutputRetMessage ret = mb->read03(slaveaddr, tREG, 1);
REQUIRE( ret.data[0] == 1 );
ModbusRTU::ReadOutputRetMessage ret2 = mb->read03(slaveaddr2, tREG, 1);
REQUIRE( ret2.data[0] == 1 );
}
// -------------------------------------------------------------
/*! \todo Доделать тесты на считывание с разными prop_prefix.. */ /*! \todo Доделать тесты на считывание с разными prop_prefix.. */
...@@ -9,9 +9,8 @@ cd ../../../Utilities/Admin/ ...@@ -9,9 +9,8 @@ cd ../../../Utilities/Admin/
cd - cd -
./uniset2-start.sh -f ./tests-with-sm $* -- --confile mbslave-test-configure.xml --e-startup-pause 10 \ ./uniset2-start.sh -f ./tests-with-sm $* -- --confile mbslave-test-configure.xml --e-startup-pause 10 \
--mbs-name MBSlave1 --mbs-type TCP --mbs-inet-addr 127.0.0.1 --mbs-inet-port 20048 --mbs-my-addr 0x01 \ --mbs-name MBSlave1 --mbs-type TCP --mbs-inet-addr 127.0.0.1 --mbs-inet-port 20048 \
--mbs-askcount-id SVU_AskCount_AS --mbs-respond-id RespondRTU_S --mbs-respond-invert 1 \ --mbs-askcount-id SVU_AskCount_AS --mbs-respond-id RespondRTU_S --mbs-respond-invert 1 \
--mbs-filter-field mbs --mbs-filter-value 1 --mbs-filter-field mbs --mbs-filter-value 1
# --dlog-add-levels any #--mbs-log-add-levels any
#--mbs-check-mbfunc 1
#--dlog-add-levels any \ No newline at end of file
...@@ -9,6 +9,6 @@ cd ../../../Utilities/Admin/ ...@@ -9,6 +9,6 @@ cd ../../../Utilities/Admin/
cd - cd -
./uniset2-start.sh -f ./tests-with-sm $* -- --apart --confile mbslave-test-configure.xml --e-startup-pause 10 \ ./uniset2-start.sh -f ./tests-with-sm $* -- --apart --confile mbslave-test-configure.xml --e-startup-pause 10 \
--mbs-name MBSlave1 --mbs-type TCP --mbs-inet-addr 127.0.0.1 --mbs-inet-port 20048 --mbs-my-addr 0x01 \ --mbs-name MBSlave1 --mbs-type TCP --mbs-inet-addr 127.0.0.1 --mbs-inet-port 20048 \
--mbs-askcount-id SVU_AskCount_AS --mbs-respond-id RespondRTU_S --mbs-respond-invert 1 \ --mbs-askcount-id SVU_AskCount_AS --mbs-respond-id RespondRTU_S --mbs-respond-invert 1 \
--mbs-filter-field mbs --mbs-filter-value 1 --mbs-filter-field mbs --mbs-filter-value 1
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define ModbusRTUSlave_H_ #define ModbusRTUSlave_H_
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
#include <string> #include <string>
#include <unordered_set>
#include "Mutex.h" #include "Mutex.h"
#include "Debug.h" #include "Debug.h"
#include "Configuration.h" #include "Configuration.h"
...@@ -31,7 +32,7 @@ class ModbusRTUSlave: ...@@ -31,7 +32,7 @@ class ModbusRTUSlave:
void setSpeed( const std::string& s ); void setSpeed( const std::string& s );
ComPort::Speed getSpeed(); ComPort::Speed getSpeed();
virtual ModbusRTU::mbErrCode receive( ModbusRTU::ModbusAddr addr, timeout_t msecTimeout ) override; virtual ModbusRTU::mbErrCode receive( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, timeout_t msecTimeout ) override;
virtual void cleanupChannel() override virtual void cleanupChannel() override
{ {
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define ModbusServer_H_ #define ModbusServer_H_
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
#include <string> #include <string>
#include <unordered_set>
#include "Debug.h" #include "Debug.h"
#include "Mutex.h" #include "Mutex.h"
...@@ -22,12 +23,20 @@ class ModbusServer ...@@ -22,12 +23,20 @@ class ModbusServer
/*! обработать очередное сообщение /*! обработать очередное сообщение
\param addr - адрес для которого принимать сообщения \param vaddr - вектор адресов для которых принимать сообщения
\param msecTimeout - время ожидания прихода очередного сообщения в мсек. \param msecTimeout - время ожидания прихода очередного сообщения в мсек.
\return Возвращает код ошибки из ModbusRTU::mbErrCode \return Возвращает код ошибки из ModbusRTU::mbErrCode
*/ */
virtual ModbusRTU::mbErrCode receive( ModbusRTU::ModbusAddr addr, timeout_t msecTimeout ) = 0; virtual ModbusRTU::mbErrCode receive( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, timeout_t msecTimeout ) = 0;
/*! Проверка входит ли данный адрес в список
* \param vaddr - вектор адресов
* \param addr - адрес который ищем
* \return TRUE - если найден
* \warning Если addr=ModbusRTU::BroadcastAddr то всегда возвращается TRUE!
*/
static bool checkAddr( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, const ModbusRTU::ModbusAddr addr );
static std::string vaddr2str( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr );
/*! Установка паузы после посылки /*! Установка паузы после посылки
\return старое значение \return старое значение
...@@ -245,7 +254,7 @@ class ModbusServer ...@@ -245,7 +254,7 @@ class ModbusServer
virtual ModbusRTU::mbErrCode processing( ModbusRTU::ModbusMessage& buf ); virtual ModbusRTU::mbErrCode processing( ModbusRTU::ModbusMessage& buf );
/*! принять сообщение из канала */ /*! принять сообщение из канала */
ModbusRTU::mbErrCode recv( ModbusRTU::ModbusAddr addr, ModbusRTU::ModbusMessage& buf, timeout_t timeout ); ModbusRTU::mbErrCode recv(const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, ModbusRTU::ModbusMessage& buf, timeout_t timeout );
ModbusRTU::mbErrCode recv_pdu( ModbusRTU::ModbusMessage& rbuf, timeout_t timeout ); ModbusRTU::mbErrCode recv_pdu( ModbusRTU::ModbusMessage& rbuf, timeout_t timeout );
UniSetTypes::uniset_mutex recvMutex; UniSetTypes::uniset_mutex recvMutex;
......
...@@ -24,13 +24,13 @@ class ModbusTCPServer: ...@@ -24,13 +24,13 @@ class ModbusTCPServer:
virtual ~ModbusTCPServer(); virtual ~ModbusTCPServer();
/*! Однопоточная обработка (каждый запрос последовательно), с разрывом соединения в конце */ /*! Однопоточная обработка (каждый запрос последовательно), с разрывом соединения в конце */
virtual ModbusRTU::mbErrCode receive( ModbusRTU::ModbusAddr mbaddr, timeout_t msecTimeout ) override; virtual ModbusRTU::mbErrCode receive( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, timeout_t msecTimeout ) override;
/*! Многопоточная обработка (создаётся по потоку для каждого "клиента") /*! Многопоточная обработка (создаётся по потоку для каждого "клиента")
\return TRUE - если запр*ос пришёл \return TRUE - если запрос пришёл
\return FALSE - если timeout \return FALSE - если timeout
*/ */
virtual bool waitQuery( ModbusRTU::ModbusAddr mbaddr, timeout_t msec = UniSetTimer::WaitUpTime ); virtual bool waitQuery( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, timeout_t msec = UniSetTimer::WaitUpTime );
void setMaxSessions( unsigned int num ); void setMaxSessions( unsigned int num );
inline unsigned int getMaxSessions() inline unsigned int getMaxSessions()
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
#include <string> #include <string>
#include <queue> #include <queue>
#include <unordered_map>
#include <cc++/socket.h> #include <cc++/socket.h>
#include "ModbusServerSlot.h" #include "ModbusServerSlot.h"
#include "ModbusServer.h" #include "ModbusServer.h"
...@@ -16,7 +17,7 @@ class ModbusTCPSession: ...@@ -16,7 +17,7 @@ class ModbusTCPSession:
{ {
public: public:
ModbusTCPSession( ost::TCPSocket& server, ModbusRTU::ModbusAddr mbaddr, timeout_t timeout ); ModbusTCPSession( ost::TCPSocket& server, const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, timeout_t timeout );
virtual ~ModbusTCPSession(); virtual ~ModbusTCPSession();
void cleanInputStream(); void cleanInputStream();
...@@ -27,7 +28,7 @@ class ModbusTCPSession: ...@@ -27,7 +28,7 @@ class ModbusTCPSession:
} }
virtual void terminate(); virtual void terminate();
virtual ModbusRTU::mbErrCode receive( ModbusRTU::ModbusAddr addr, timeout_t msecTimeout ); virtual ModbusRTU::mbErrCode receive( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, timeout_t msecTimeout );
typedef sigc::slot<void, ModbusTCPSession*> FinalSlot; typedef sigc::slot<void, ModbusTCPSession*> FinalSlot;
...@@ -99,7 +100,7 @@ class ModbusTCPSession: ...@@ -99,7 +100,7 @@ class ModbusTCPSession:
private: private:
std::queue<unsigned char> qrecv; std::queue<unsigned char> qrecv;
ModbusTCP::MBAPHeader curQueryHeader; ModbusTCP::MBAPHeader curQueryHeader;
ModbusRTU::ModbusAddr addr; std::unordered_set<ModbusRTU::ModbusAddr> vaddr;
PassiveTimer ptTimeout; PassiveTimer ptTimeout;
timeout_t timeout; timeout_t timeout;
ModbusRTU::ModbusMessage buf; ModbusRTU::ModbusMessage buf;
......
...@@ -63,7 +63,7 @@ ModbusRTUSlave::~ModbusRTUSlave() ...@@ -63,7 +63,7 @@ ModbusRTUSlave::~ModbusRTUSlave()
delete port; delete port;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlave::receive( ModbusRTU::ModbusAddr addr, timeout_t timeout ) mbErrCode ModbusRTUSlave::receive(const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t timeout )
{ {
uniset_mutex_lock lck(recvMutex, timeout); uniset_mutex_lock lck(recvMutex, timeout);
...@@ -80,7 +80,7 @@ mbErrCode ModbusRTUSlave::receive( ModbusRTU::ModbusAddr addr, timeout_t timeout ...@@ -80,7 +80,7 @@ mbErrCode ModbusRTUSlave::receive( ModbusRTU::ModbusAddr addr, timeout_t timeout
do do
{ {
res = recv(addr, buf, timeout); res = recv(vmbaddr, buf, timeout);
if( res != erNoError && res != erBadReplyNodeAddress ) if( res != erNoError && res != erBadReplyNodeAddress )
{ {
...@@ -94,9 +94,9 @@ mbErrCode ModbusRTUSlave::receive( ModbusRTU::ModbusAddr addr, timeout_t timeout ...@@ -94,9 +94,9 @@ mbErrCode ModbusRTUSlave::receive( ModbusRTU::ModbusAddr addr, timeout_t timeout
printProcessingTime(); printProcessingTime();
} }
// dlog->warn() << "(receive): " << mbErr2Str(res) << endl; if( aftersend_msec >= 0 )
// cerr << "**** (receive): " << mbErr2Str(res) << endl; msleep(aftersend_msec);
usleep(10000); // usleep(10000);
return res; return res;
} }
......
...@@ -66,6 +66,26 @@ timeout_t ModbusServer::setAfterSendPause( timeout_t msec ) ...@@ -66,6 +66,26 @@ timeout_t ModbusServer::setAfterSendPause( timeout_t msec )
return old; return old;
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
bool ModbusServer::checkAddr(const std::unordered_set<ModbusAddr>& vaddr, const ModbusRTU::ModbusAddr addr )
{
if( addr == ModbusRTU::BroadcastAddr )
return true;
auto i = vaddr.find(addr);
return (i!=vaddr.end());
}
// --------------------------------------------------------------------------------
std::string ModbusServer::vaddr2str( const std::unordered_set<ModbusAddr>& vaddr )
{
ostringstream s;
s << "[ ";
for( const auto& a: vaddr )
s << addr2str(a) << " ";
s <<"]";
return std::move(s.str());
}
// --------------------------------------------------------------------------------
mbErrCode ModbusServer::processing( ModbusMessage& buf ) mbErrCode ModbusServer::processing( ModbusMessage& buf )
{ {
if( buf.func == fnReadCoilStatus ) if( buf.func == fnReadCoilStatus )
...@@ -540,7 +560,7 @@ mbErrCode ModbusServer::processing( ModbusMessage& buf ) ...@@ -540,7 +560,7 @@ mbErrCode ModbusServer::processing( ModbusMessage& buf )
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusServer::recv( ModbusRTU::ModbusAddr addr, ModbusMessage& rbuf, timeout_t timeout ) mbErrCode ModbusServer::recv( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, ModbusMessage& rbuf, timeout_t timeout )
{ {
assert(timeout); assert(timeout);
...@@ -563,7 +583,7 @@ mbErrCode ModbusServer::recv( ModbusRTU::ModbusAddr addr, ModbusMessage& rbuf, t ...@@ -563,7 +583,7 @@ mbErrCode ModbusServer::recv( ModbusRTU::ModbusAddr addr, ModbusMessage& rbuf, t
{ {
bcnt = getNextData((unsigned char*)(&rbuf), sizeof(ModbusAddr)); bcnt = getNextData((unsigned char*)(&rbuf), sizeof(ModbusAddr));
if( bcnt > 0 && ( rbuf.addr == addr || (onBroadcast && rbuf.addr == BroadcastAddr) || addr == BroadcastAddr ) ) if( bcnt > 0 && checkAddr(vaddr,rbuf.addr) )
{ {
begin = true; begin = true;
break; break;
...@@ -579,12 +599,12 @@ mbErrCode ModbusServer::recv( ModbusRTU::ModbusAddr addr, ModbusMessage& rbuf, t ...@@ -579,12 +599,12 @@ mbErrCode ModbusServer::recv( ModbusRTU::ModbusAddr addr, ModbusMessage& rbuf, t
// Lav: конечно стоит, нам же надо буфер чистить // Lav: конечно стоит, нам же надо буфер чистить
*/ */
// Проверка кому адресован пакет... (только если не включён режим отвечать на любые адреса) // Проверка кому адресован пакет... (только если не включён режим отвечать на любые адреса)
if( addr != BroadcastAddr && rbuf.addr != addr && rbuf.addr != BroadcastAddr ) if( !(onBroadcast && rbuf.addr == BroadcastAddr) && !checkAddr(vaddr,rbuf.addr) )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
ostringstream err; ostringstream err;
err << "(recv): BadNodeAddress. my= " << addr2str(addr) err << "(recv): BadNodeAddress. my= " << vaddr2str(vaddr)
<< " msg.addr=" << addr2str(rbuf.addr); << " msg.addr=" << addr2str(rbuf.addr);
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
} }
......
...@@ -54,7 +54,7 @@ void ModbusTCPServer::setSessionTimeout( timeout_t msec ) ...@@ -54,7 +54,7 @@ void ModbusTCPServer::setSessionTimeout( timeout_t msec )
sessTimeout = msec; sessTimeout = msec;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPServer::waitQuery( ModbusRTU::ModbusAddr mbaddr, timeout_t msec ) bool ModbusTCPServer::waitQuery(const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t msec )
{ {
if( msec == 0 ) if( msec == 0 )
msec = UniSetTimer::WaitUpTime; msec = UniSetTimer::WaitUpTime;
...@@ -72,7 +72,7 @@ bool ModbusTCPServer::waitQuery( ModbusRTU::ModbusAddr mbaddr, timeout_t msec ) ...@@ -72,7 +72,7 @@ bool ModbusTCPServer::waitQuery( ModbusRTU::ModbusAddr mbaddr, timeout_t msec )
if( cancelled ) if( cancelled )
return false; return false;
ModbusTCPSession* s = new ModbusTCPSession(*this, mbaddr, sessTimeout); ModbusTCPSession* s = new ModbusTCPSession(*this, vmbaddr, sessTimeout);
s->connectReadCoil( sigc::mem_fun(this, &ModbusTCPServer::readCoilStatus) ); s->connectReadCoil( sigc::mem_fun(this, &ModbusTCPServer::readCoilStatus) );
s->connectReadInputStatus( sigc::mem_fun(this, &ModbusTCPServer::readInputStatus) ); s->connectReadInputStatus( sigc::mem_fun(this, &ModbusTCPServer::readInputStatus) );
...@@ -118,7 +118,7 @@ bool ModbusTCPServer::waitQuery( ModbusRTU::ModbusAddr mbaddr, timeout_t msec ) ...@@ -118,7 +118,7 @@ bool ModbusTCPServer::waitQuery( ModbusRTU::ModbusAddr mbaddr, timeout_t msec )
return false; return false;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeout ) mbErrCode ModbusTCPServer::receive(const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t timeout )
{ {
PassiveTimer ptTimeout(timeout); PassiveTimer ptTimeout(timeout);
ModbusMessage buf; ModbusMessage buf;
...@@ -171,46 +171,21 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou ...@@ -171,46 +171,21 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou
} }
} }
if( !qrecv.empty() ) if( qrecv.empty() )
{ {
// check addr tcp.disconnect();
unsigned char _addr = qrecv.front(); return erTimeOut;
// для режима игнорирования RTU-адреса
// просто подменяем его на то который пришёл
// чтобы проверка всегда была успешной...
if( ignoreAddr )
addr = _addr;
else if( (onBroadcast && _addr == BroadcastAddr) || addr==ModbusRTU::BroadcastAddr )
{
// нормально обрабатываем..
}
else if( _addr != addr )
{
res = erTimeOut;
// На такие запросы просто не отвечаем...
/*
res = erBadReplyNodeAddress;
tmProcessing.setTiming(replyTimeout_ms);
ErrorRetMessage em( _addr, buf.func, res );
buf = em.transport_msg();
send(buf);
printProcessingTime();
if( aftersend_msec >= 0 )
msleep(aftersend_msec);
*/
tcp.disconnect();
return res;
}
} }
res = recv( addr, buf, timeout ); unsigned char q_addr = qrecv.front();
res = recv( vmbaddr, buf, timeout );
if( res != erNoError ) // && res!=erBadReplyNodeAddress ) if( res != erNoError ) // && res!=erBadReplyNodeAddress )
{ {
if( res < erInternalErrorCode ) if( res < erInternalErrorCode )
{ {
ErrorRetMessage em( addr, buf.func, res ); ErrorRetMessage em( q_addr, buf.func, res );
buf = em.transport_msg(); buf = em.transport_msg();
send(buf); send(buf);
printProcessingTime(); printProcessingTime();
...@@ -247,9 +222,10 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou ...@@ -247,9 +222,10 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou
tcp.disconnect(); tcp.disconnect();
} }
} }
catch( ost::Exception& e ) catch( const ost::Exception& e )
{ {
cout << "(ModbusTCPServer): " << e.what() << endl; if( dlog->is_crit() )
dlog->crit() << "(ModbusTCPServer): " << e.what() << endl;
return erInternalErrorCode; return erInternalErrorCode;
} }
......
...@@ -22,9 +22,9 @@ ModbusTCPSession::~ModbusTCPSession() ...@@ -22,9 +22,9 @@ ModbusTCPSession::~ModbusTCPSession()
ost::Thread::join(); ost::Thread::join();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPSession::ModbusTCPSession( ost::TCPSocket& server, ModbusRTU::ModbusAddr a, timeout_t timeout ): ModbusTCPSession::ModbusTCPSession(ost::TCPSocket& server, const std::unordered_set<ModbusAddr>& a, timeout_t timeout ):
TCPSession(server), TCPSession(server),
addr(a), vaddr(a),
timeout(timeout), timeout(timeout),
peername(""), peername(""),
caddr(""), caddr(""),
...@@ -94,7 +94,7 @@ void ModbusTCPSession::run() ...@@ -94,7 +94,7 @@ void ModbusTCPSession::run()
if( n == 0 ) if( n == 0 )
break; break;
res = receive(addr, timeout); res = receive(vaddr, timeout);
if( res == erSessionClosed ) if( res == erSessionClosed )
break; break;
...@@ -118,7 +118,7 @@ void ModbusTCPSession::run() ...@@ -118,7 +118,7 @@ void ModbusTCPSession::run()
dlog->info() << peername << "(run): thread stopping..." << endl; dlog->info() << peername << "(run): thread stopping..." << endl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPSession::receive( ModbusRTU::ModbusAddr addr, timeout_t msec ) ModbusRTU::mbErrCode ModbusTCPSession::receive( const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t msec )
{ {
ModbusRTU::mbErrCode res = erTimeOut; ModbusRTU::mbErrCode res = erTimeOut;
ptTimeout.setTiming(msec); ptTimeout.setTiming(msec);
...@@ -138,28 +138,16 @@ ModbusRTU::mbErrCode ModbusTCPSession::receive( ModbusRTU::ModbusAddr addr, time ...@@ -138,28 +138,16 @@ ModbusRTU::mbErrCode ModbusTCPSession::receive( ModbusRTU::ModbusAddr addr, time
return erTimeOut; return erTimeOut;
} }
if( !qrecv.empty() ) if( qrecv.empty() )
{ return erTimeOut;
// check addr
unsigned char _addr = qrecv.front(); unsigned char q_addr = qrecv.front();
// для режима игнорирования RTU-адреса
// просто подменяем его на то который пришёл
// чтобы проверка всегда была успешной...
if( ignoreAddr )
addr = _addr;
else if( _addr != addr )
{
// На такие запросы просто не отвечаем...
return erTimeOut;
}
}
if( cancelled ) if( cancelled )
return erSessionClosed; return erSessionClosed;
memset(&buf, 0, sizeof(buf)); memset(&buf, 0, sizeof(buf));
res = recv( addr, buf, msec ); res = recv( vmbaddr, buf, msec );
if( cancelled ) if( cancelled )
return erSessionClosed; return erSessionClosed;
...@@ -168,7 +156,7 @@ ModbusRTU::mbErrCode ModbusTCPSession::receive( ModbusRTU::ModbusAddr addr, time ...@@ -168,7 +156,7 @@ ModbusRTU::mbErrCode ModbusTCPSession::receive( ModbusRTU::ModbusAddr addr, time
{ {
if( res < erInternalErrorCode ) if( res < erInternalErrorCode )
{ {
ErrorRetMessage em( addr, buf.func, res ); ErrorRetMessage em( q_addr, buf.func, res );
buf = em.transport_msg(); buf = em.transport_msg();
send(buf); send(buf);
printProcessingTime(); printProcessingTime();
......
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