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;
} }
......
...@@ -14,7 +14,6 @@ using namespace ModbusRTU; ...@@ -14,7 +14,6 @@ using namespace ModbusRTU;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const std::shared_ptr<SharedMemory>& ic, const string& prefix ): MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const std::shared_ptr<SharedMemory>& ic, const string& prefix ):
UniSetObject_LT(objId), UniSetObject_LT(objId),
addr(0x01),
initPause(0), initPause(0),
test_id(DefaultObjectId), test_id(DefaultObjectId),
askcount_id(DefaultObjectId), askcount_id(DefaultObjectId),
...@@ -109,9 +108,7 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const ...@@ -109,9 +108,7 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const
vmonit(force); vmonit(force);
addr = ModbusRTU::str2mbAddr(conf->getArg2Param("--" + prefix + "-my-addr", it.getProp("addr"), "0x01")); default_mbaddr = conf->getArg2Param("--" + prefix + "-default-mbaddr", it.getProp("default_mbaddr"), "");
vmonit(addr);
default_mbfunc = conf->getArgPInt("--" + prefix + "-default-mbfunc", it.getProp("default_mbfunc"), 0); default_mbfunc = conf->getArgPInt("--" + prefix + "-default-mbfunc", it.getProp("default_mbfunc"), 0);
mbregFromID = conf->getArgInt("--" + prefix + "-reg-from-id", it.getProp("reg_from_id")); mbregFromID = conf->getArgInt("--" + prefix + "-reg-from-id", it.getProp("reg_from_id"));
...@@ -120,14 +117,15 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const ...@@ -120,14 +117,15 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const
mbinfo << myname << "(init): mbregFromID=" << mbregFromID mbinfo << myname << "(init): mbregFromID=" << mbregFromID
<< " checkMBFunc=" << checkMBFunc << " checkMBFunc=" << checkMBFunc
<< " default_mbfunc=" << default_mbfunc << " default_mbfunc=" << default_mbfunc
<< " default_mbaddr=" << default_mbaddr
<< " noMBFuncOptimize=" << noMBFuncOptimize << " noMBFuncOptimize=" << noMBFuncOptimize
<< endl; << endl;
vmonit(default_mbaddr);
vmonit(default_mbfunc); vmonit(default_mbfunc);
vmonit(checkMBFunc); vmonit(checkMBFunc);
vmonit(noMBFuncOptimize); vmonit(noMBFuncOptimize);
respond_id = conf->getSensorID(conf->getArgParam("--" + prefix + "-respond-id", it.getProp("respond_id"))); respond_id = conf->getSensorID(conf->getArgParam("--" + prefix + "-respond-id", it.getProp("respond_id")));
respond_invert = conf->getArgInt("--" + prefix + "-respond-invert", it.getProp("respond_invert")); respond_invert = conf->getArgInt("--" + prefix + "-respond-invert", it.getProp("respond_invert"));
...@@ -159,13 +157,11 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const ...@@ -159,13 +157,11 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const
rs->setAfterSendPause(aftersend_pause); rs->setAfterSendPause(aftersend_pause);
rs->setReplyTimeout(reply_tout); rs->setReplyTimeout(reply_tout);
rs->setLog(mblog); rs->setLog(mblog);
rs->setBroadcastMode( addr == ModbusRTU::BroadcastAddr );
mbslot = std::static_pointer_cast<ModbusServerSlot>(rs); mbslot = std::static_pointer_cast<ModbusServerSlot>(rs);
thr = make_shared< ThreadCreator<MBSlave> >(this, &MBSlave::execute_rtu); thr = make_shared< ThreadCreator<MBSlave> >(this, &MBSlave::execute_rtu);
thr->setFinalAction(this, &MBSlave::finalThread); thr->setFinalAction(this, &MBSlave::finalThread);
mbinfo << myname << "(init): type=RTU myaddr=" << ModbusRTU::addr2str(addr) mbinfo << myname << "(init): type=RTU dev=" << dev << " speed=" << speed << endl;
<< " dev=" << dev << " speed=" << speed << endl;
} }
else if( stype == "TCP" ) else if( stype == "TCP" )
{ {
...@@ -176,15 +172,13 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const ...@@ -176,15 +172,13 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const
int port = conf->getArgPInt("--" + prefix + "-inet-port", it.getProp("iport"), 502); int port = conf->getArgPInt("--" + prefix + "-inet-port", it.getProp("iport"), 502);
mbinfo << myname << "(init): type=TCP myaddr=" << ModbusRTU::addr2str(addr) mbinfo << myname << "(init): type=TCP inet=" << iaddr << " port=" << port << endl;
<< " inet=" << iaddr << " port=" << port << endl;
ost::InetAddress ia(iaddr.c_str()); ost::InetAddress ia(iaddr.c_str());
auto mbtcp = make_shared<ModbusTCPServerSlot>(ia, port); auto mbtcp = make_shared<ModbusTCPServerSlot>(ia, port);
mbtcp->setAfterSendPause(aftersend_pause); mbtcp->setAfterSendPause(aftersend_pause);
mbtcp->setReplyTimeout(reply_tout); mbtcp->setReplyTimeout(reply_tout);
mbtcp->setBroadcastMode( addr == ModbusRTU::BroadcastAddr );
mbslot = std::static_pointer_cast<ModbusServerSlot>(mbtcp); mbslot = std::static_pointer_cast<ModbusServerSlot>(mbtcp);
thr = make_shared< ThreadCreator<MBSlave> >(this, &MBSlave::execute_tcp); thr = make_shared< ThreadCreator<MBSlave> >(this, &MBSlave::execute_tcp);
...@@ -222,7 +216,8 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const ...@@ -222,7 +216,8 @@ MBSlave::MBSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const
if( shm->isLocalwork() ) if( shm->isLocalwork() )
{ {
readConfiguration(); readConfiguration();
mbinfo << myname << "(init): iomap size = " << iomap.size() << endl; mbinfo << myname << "(init): iomap size = " << iomap.size()
<< " myaddr=" << ModbusServer::vaddr2str(vaddr) << endl;
} }
else else
{ {
...@@ -491,11 +486,32 @@ void MBSlave::execute_rtu() ...@@ -491,11 +486,32 @@ void MBSlave::execute_rtu()
ModbusRTU::mbErrCode prev = erNoError; ModbusRTU::mbErrCode prev = erNoError;
// ждём чтобы прошла инициализация
// потому-что нужно чтобы наполнилась таблица адресов (vaddr)
if( !shm->isLocalwork() )
{
std::unique_lock<std::mutex> locker(mutexStartNotify);
while( !activated )
startNotifyEvent.wait(locker);
}
if( vaddr.empty() )
{
mbcrit << "(execute_rtu): Unknown my modbus adresses!" << endl;
raise(SIGTERM);
return;
}
mbinfo << myname << "(execute_rtu): thread running.."
<< " iomap size = " << iomap.size()
<< " myaddr=" << ModbusServer::vaddr2str(vaddr)
<< endl;
while( !cancelled ) while( !cancelled )
{ {
try try
{ {
ModbusRTU::mbErrCode res = rscomm->receive( addr, wait_msec ); ModbusRTU::mbErrCode res = rscomm->receive( vaddr, wait_msec );
if( res != ModbusRTU::erTimeOut ) if( res != ModbusRTU::erTimeOut )
ptTimeout.reset(); ptTimeout.reset();
...@@ -561,8 +577,11 @@ void MBSlave::execute_rtu() ...@@ -561,8 +577,11 @@ void MBSlave::execute_rtu()
} }
} }
for( auto && it : iomap ) for( auto&& rmap: iomap )
IOBase::processingThreshold(&it.second, shm, force); {
for( auto&& it: rmap.second )
IOBase::processingThreshold(&it.second, shm, force);
}
} }
catch(...) {} catch(...) {}
} }
...@@ -574,13 +593,32 @@ void MBSlave::execute_tcp() ...@@ -574,13 +593,32 @@ void MBSlave::execute_tcp()
ModbusRTU::mbErrCode prev = erNoError; ModbusRTU::mbErrCode prev = erNoError;
mbinfo << myname << "(execute_tcp): thread running.." << endl; // ждём чтобы прошла инициализация
// потому-что нужно чтобы наполнилась таблица адресов (vaddr)
if( !shm->isLocalwork() )
{
std::unique_lock<std::mutex> locker(mutexStartNotify);
while( !activated )
startNotifyEvent.wait(locker);
}
if( vaddr.empty() )
{
mbcrit << "(execute_rtu): Unknown my modbus adresses!" << endl;
raise(SIGTERM);
return;
}
mbinfo << myname << "(execute_tcp): thread running.."
<< " iomap size = " << iomap.size()
<< " myaddr=" << ModbusServer::vaddr2str(vaddr)
<< endl;
while( !cancelled ) while( !cancelled )
{ {
try try
{ {
ModbusRTU::mbErrCode res = sslot->receive( addr, wait_msec ); ModbusRTU::mbErrCode res = sslot->receive( vaddr, wait_msec );
if( res != ModbusRTU::erTimeOut ) if( res != ModbusRTU::erTimeOut )
ptTimeout.reset(); ptTimeout.reset();
...@@ -647,8 +685,11 @@ void MBSlave::execute_tcp() ...@@ -647,8 +685,11 @@ void MBSlave::execute_tcp()
} }
} }
for( auto && it : iomap ) for( auto&& rmap: iomap )
IOBase::processingThreshold(&it.second, shm, force); {
for( auto&& it : rmap.second )
IOBase::processingThreshold(&it.second, shm, force);
}
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
...@@ -761,68 +802,75 @@ void MBSlave::askSensors( UniversalIO::UIOCommand cmd ) ...@@ -761,68 +802,75 @@ void MBSlave::askSensors( UniversalIO::UIOCommand cmd )
if( force ) if( force )
return; return;
for( const auto& it : iomap ) for( const auto& rmap: iomap )
{ {
const IOProperty* p(&it.second); for( const auto& it : rmap.second )
try
{
shm->askSensor(p->si.id, cmd);
}
catch( const UniSetTypes::Exception& ex )
{ {
mbwarn << myname << "(askSensors): " << ex << std::endl; const IOProperty* p(&it.second);
try
{
shm->askSensor(p->si.id, cmd);
}
catch( const UniSetTypes::Exception& ex )
{
mbwarn << myname << "(askSensors): " << ex << std::endl;
}
catch(...) {}
} }
catch(...) {}
} }
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void MBSlave::sensorInfo( const UniSetTypes::SensorMessage* sm ) void MBSlave::sensorInfo( const UniSetTypes::SensorMessage* sm )
{ {
for( auto it = iomap.begin(); it != iomap.end(); ++it ) for( auto&& regs: iomap )
{ {
if( it->second.si.id == sm->id ) auto& rmap = regs.second;
for( auto it =rmap.begin(); it != rmap.end(); ++it )
{ {
IOProperty* p(&it->second); if( it->second.si.id == sm->id )
if( p->stype == UniversalIO::DO ||
p->stype == UniversalIO::DI )
{
uniset_rwmutex_wrlock lock(p->val_lock);
p->value = sm->value ? 1 : 0;
}
else if( p->stype == UniversalIO::AO ||
p->stype == UniversalIO::AI )
{ {
uniset_rwmutex_wrlock lock(p->val_lock); IOProperty* p(&it->second);
p->value = sm->value;
}
int sz = VTypes::wsize(p->vtype); if( p->stype == UniversalIO::DO ||
p->stype == UniversalIO::DI )
{
uniset_rwmutex_wrlock lock(p->val_lock);
p->value = sm->value ? 1 : 0;
}
else if( p->stype == UniversalIO::AO ||
p->stype == UniversalIO::AI )
{
uniset_rwmutex_wrlock lock(p->val_lock);
p->value = sm->value;
}
if( sz < 1 ) int sz = VTypes::wsize(p->vtype);
return;
// если размер больше одного слова if( sz < 1 )
// то надо обновить значение "везде" return;
// они если "всё верно инициализировано" идут подряд
int i = 0;
for( ; i < sz && it != iomap.end(); i++, it++ ) // если размер больше одного слова
{ // то надо обновить значение "везде"
p = &it->second; // они если "всё верно инициализировано" идут подряд
int i = 0;
if( p->si.id == sm->id ) for( ; i < sz && it != rmap.end(); i++, it++ )
p->value = sm->value; {
} p = &it->second;
if( p->si.id == sm->id )
p->value = sm->value;
}
// вообще этого не может случиться // вообще этого не может случиться
// потому-что корректность проверяется при загрузке // потому-что корректность проверяется при загрузке
if( i != sz ) if( i != sz )
mbcrit << myname << "(sensorInfo): update failed for sid=" << sm->id mbcrit << myname << "(sensorInfo): update failed for sid=" << sm->id
<< " (i=" << i << " sz=" << sz << ")" << endl; << " (i=" << i << " sz=" << sz << ")" << endl;
return; return;
}
} }
} }
} }
...@@ -838,6 +886,7 @@ bool MBSlave::activateObject() ...@@ -838,6 +886,7 @@ bool MBSlave::activateObject()
UniSetObject_LT::activateObject(); UniSetObject_LT::activateObject();
initIterators(); initIterators();
activated = true; activated = true;
startNotifyEvent.notify_all();
} }
return true; return true;
...@@ -921,6 +970,21 @@ bool MBSlave::initItem( UniXML::iterator& it ) ...@@ -921,6 +970,21 @@ bool MBSlave::initItem( UniXML::iterator& it )
if( !IOBase::initItem( static_cast<IOBase*>(&p), it, shm, prop_prefix, false, mblog, myname) ) if( !IOBase::initItem( static_cast<IOBase*>(&p), it, shm, prop_prefix, false, mblog, myname) )
return false; return false;
std::string s_mbaddr = IOBase::initProp(it, "mbaddr", prop_prefix, false, default_mbaddr);
if( s_mbaddr.empty() )
{
mbcrit << myname << "(initItem): Unknown '" << prop_prefix << "mbaddr' for " << it.getProp("name") << endl;
return false;
}
ModbusAddr mbaddr = ModbusRTU::str2mbAddr(s_mbaddr);
// наполняем "таблицу" адресов устройства
vaddr.emplace(mbaddr); // вставляем всегда (независимо есть или нет уже элемент)
RegMap& rmap = iomap[mbaddr]; // создаём элемент (если его ещё нет) и сразу используем
if( mbregFromID ) if( mbregFromID )
p.mbreg = p.si.id; p.mbreg = p.si.id;
else else
...@@ -968,9 +1032,9 @@ bool MBSlave::initItem( UniXML::iterator& it ) ...@@ -968,9 +1032,9 @@ bool MBSlave::initItem( UniXML::iterator& it )
return false; return false;
} }
auto i = iomap.find(p.regID); auto i = rmap.find(p.regID);
if( i != iomap.end() ) if( i != rmap.end() )
{ {
if( !i->second.bitreg ) if( !i->second.bitreg )
{ {
...@@ -1004,7 +1068,6 @@ bool MBSlave::initItem( UniXML::iterator& it ) ...@@ -1004,7 +1068,6 @@ bool MBSlave::initItem( UniXML::iterator& it )
IOBase b = p.make_iobase_copy(); IOBase b = p.make_iobase_copy();
AccessMode p_amode = p.amode; AccessMode p_amode = p.amode;
VTypes::VType p_vtype = p.vtype;
int p_nbyte = p.nbyte; int p_nbyte = p.nbyte;
bool p_rawdata = p.rawdata; bool p_rawdata = p.rawdata;
...@@ -1022,15 +1085,15 @@ bool MBSlave::initItem( UniXML::iterator& it ) ...@@ -1022,15 +1085,15 @@ bool MBSlave::initItem( UniXML::iterator& it )
p_dummy.bitreg->bvec[nbit] = std::move(p); // после этого p использовать нельзя! p_dummy.bitreg->bvec[nbit] = std::move(p); // после этого p использовать нельзя!
mbinfo << myname << "(initItem): add bit register: " << p_dummy.bitreg.get() << endl; mbinfo << myname << "(initItem): add bit register: " << p_dummy.bitreg.get() << endl;
iomap[p_dummy.regID] = std::move(p_dummy); rmap[p_dummy.regID] = std::move(p_dummy);
} }
return true; return true;
} }
auto i = iomap.find(p.regID); auto i = rmap.find(p.regID);
if( i != iomap.end() ) if( i != rmap.end() )
{ {
ostringstream err; ostringstream err;
err << myname << "(initItem): FAIL ADD sid='" << it.getProp("name") << "'(" << p.si.id << ")" err << myname << "(initItem): FAIL ADD sid='" << it.getProp("name") << "'(" << p.si.id << ")"
...@@ -1053,7 +1116,7 @@ bool MBSlave::initItem( UniXML::iterator& it ) ...@@ -1053,7 +1116,7 @@ bool MBSlave::initItem( UniXML::iterator& it )
p.vtype = VTypes::vtUnknown; p.vtype = VTypes::vtUnknown;
p.wnum = 0; p.wnum = 0;
mbinfo << myname << "(initItem): add " << p << endl; mbinfo << myname << "(initItem): add " << p << endl;
iomap[p.regID] = std::move(p); rmap[p.regID] = std::move(p);
} }
else else
{ {
...@@ -1107,7 +1170,7 @@ bool MBSlave::initItem( UniXML::iterator& it ) ...@@ -1107,7 +1170,7 @@ bool MBSlave::initItem( UniXML::iterator& it )
// после std::move p - использовать нельзя! // после std::move p - использовать нельзя!
mbinfo << myname << "(initItem): add " << p << endl; mbinfo << myname << "(initItem): add " << p << endl;
iomap[p_regID] = std::move(p); rmap[p_regID] = std::move(p);
if( wsz > 1 ) if( wsz > 1 )
{ {
...@@ -1125,7 +1188,7 @@ bool MBSlave::initItem( UniXML::iterator& it ) ...@@ -1125,7 +1188,7 @@ bool MBSlave::initItem( UniXML::iterator& it )
p_dummy.regID = p_regID; p_dummy.regID = p_regID;
mbinfo << myname << "(initItem): add " << p_dummy << endl; mbinfo << myname << "(initItem): add " << p_dummy << endl;
iomap[p_regID] = std::move(p_dummy); rmap[p_regID] = std::move(p_dummy);
} }
} }
} }
...@@ -1160,18 +1223,23 @@ bool MBSlave::BitRegProperty::check( const IOController_i::SensorInfo& si ) ...@@ -1160,18 +1223,23 @@ bool MBSlave::BitRegProperty::check( const IOController_i::SensorInfo& si )
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void MBSlave::initIterators() void MBSlave::initIterators()
{ {
auto it = iomap.begin(); for( auto&& regs: iomap )
for( ; it != iomap.end(); ++it )
{ {
shm->initIterator(it->second.ioit); auto& rmap = regs.second;
auto it = rmap.begin();
if( it->second.bitreg ) for( ; it != rmap.end(); ++it )
{ {
auto b = it->second.bitreg; shm->initIterator(it->second.ioit);
for( auto i = b->bvec.begin(); i != b->bvec.end(); ++ i ) if( it->second.bitreg )
shm->initIterator(i->ioit); {
auto b = it->second.bitreg;
for( auto i = b->bvec.begin(); i != b->bvec.end(); ++ i )
shm->initIterator(i->ioit);
}
} }
} }
...@@ -1302,10 +1370,17 @@ ModbusRTU::mbErrCode MBSlave::readOutputRegisters( ModbusRTU::ReadOutputMessage& ...@@ -1302,10 +1370,17 @@ ModbusRTU::mbErrCode MBSlave::readOutputRegisters( ModbusRTU::ReadOutputMessage&
{ {
mbinfo << myname << "(readOutputRegisters): " << query << endl; mbinfo << myname << "(readOutputRegisters): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(readOutputRegisters): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
if( query.count <= 1 ) if( query.count <= 1 )
{ {
ModbusRTU::ModbusData d = 0; ModbusRTU::ModbusData d = 0;
ModbusRTU::mbErrCode ret = real_read(query.start, d, query.func); ModbusRTU::mbErrCode ret = real_read(regmap->second, query.start, d, query.func);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
reply.addData(d); reply.addData(d);
...@@ -1316,7 +1391,7 @@ ModbusRTU::mbErrCode MBSlave::readOutputRegisters( ModbusRTU::ReadOutputMessage& ...@@ -1316,7 +1391,7 @@ ModbusRTU::mbErrCode MBSlave::readOutputRegisters( ModbusRTU::ReadOutputMessage&
} }
// Фомирование ответа: // Фомирование ответа:
ModbusRTU::mbErrCode ret = much_real_read(query.start, buf, query.count, query.func); ModbusRTU::mbErrCode ret = much_real_read(regmap->second, query.start, buf, query.count, query.func);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
{ {
...@@ -1333,9 +1408,16 @@ ModbusRTU::mbErrCode MBSlave::writeOutputRegisters( ModbusRTU::WriteOutputMessag ...@@ -1333,9 +1408,16 @@ ModbusRTU::mbErrCode MBSlave::writeOutputRegisters( ModbusRTU::WriteOutputMessag
{ {
mbinfo << myname << "(writeOutputRegisters): " << query << endl; mbinfo << myname << "(writeOutputRegisters): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(writeOutputRegisters): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
// Формирование ответа: // Формирование ответа:
int fn = getOptimizeWriteFunction(query.func); int fn = getOptimizeWriteFunction(query.func);
ModbusRTU::mbErrCode ret = much_real_write(query.start, query.data, query.quant, fn); ModbusRTU::mbErrCode ret = much_real_write(regmap->second, query.start, query.data, query.quant, fn);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
reply.set(query.start, query.quant); reply.set(query.start, query.quant);
...@@ -1348,8 +1430,15 @@ ModbusRTU::mbErrCode MBSlave::writeOutputSingleRegister( ModbusRTU::WriteSingleO ...@@ -1348,8 +1430,15 @@ ModbusRTU::mbErrCode MBSlave::writeOutputSingleRegister( ModbusRTU::WriteSingleO
{ {
mbinfo << myname << "(writeOutputSingleRegisters): " << query << endl; mbinfo << myname << "(writeOutputSingleRegisters): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(writeOutputRegisters): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
int fn = getOptimizeWriteFunction(query.func); int fn = getOptimizeWriteFunction(query.func);
ModbusRTU::mbErrCode ret = real_write(query.start, query.data, fn); ModbusRTU::mbErrCode ret = real_write(regmap->second, query.start, query.data, fn);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
reply.set(query.start, query.data); reply.set(query.start, query.data);
...@@ -1357,14 +1446,14 @@ ModbusRTU::mbErrCode MBSlave::writeOutputSingleRegister( ModbusRTU::WriteSingleO ...@@ -1357,14 +1446,14 @@ ModbusRTU::mbErrCode MBSlave::writeOutputSingleRegister( ModbusRTU::WriteSingleO
return ret; return ret;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::much_real_write( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, ModbusRTU::mbErrCode MBSlave::much_real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat,
int count, const int fn ) int count, const int fn )
{ {
mbinfo << myname << "(much_real_write): write mbID=" mbinfo << myname << "(much_real_write): write mbID="
<< ModbusRTU::dat2str(reg) << "(" << (int)reg << ")" << " count=" << count << " fn=" << fn << endl; << ModbusRTU::dat2str(reg) << "(" << (int)reg << ")" << " count=" << count << " fn=" << fn << endl;
int i = 0; int i = 0;
auto it = iomap.end(); auto it = rmap.end();
int mbfunc = checkMBFunc ? fn : default_mbfunc; int mbfunc = checkMBFunc ? fn : default_mbfunc;
ModbusRTU::RegID regID = genRegID(reg, mbfunc); ModbusRTU::RegID regID = genRegID(reg, mbfunc);
...@@ -1373,28 +1462,28 @@ ModbusRTU::mbErrCode MBSlave::much_real_write( const ModbusRTU::ModbusData reg, ...@@ -1373,28 +1462,28 @@ ModbusRTU::mbErrCode MBSlave::much_real_write( const ModbusRTU::ModbusData reg,
// ведь запросить могут начиная с "несуществующего регистра" // ведь запросить могут начиная с "несуществующего регистра"
for( ; i < count; i++ ) for( ; i < count; i++ )
{ {
it = iomap.find(regID + i); it = rmap.find(regID + i);
if( it != iomap.end() ) if( it != rmap.end() )
{ {
regID += i; regID += i;
break; break;
} }
} }
if( it == iomap.end() ) if( it == rmap.end() )
return ModbusRTU::erBadDataAddress; return ModbusRTU::erBadDataAddress;
int prev_i = i; int prev_i = i;
int sub = 0; int sub = 0;
for( ; (it != iomap.end()) && (i < count); ) for( ; (it != rmap.end()) && (i < count); )
{ {
if( it->first == regID ) if( it->first == regID )
{ {
prev_i = i; prev_i = i;
real_write_it(it, dat, i, count); real_write_it(rmap, it, dat, i, count);
sub = (i - prev_i); sub = (i - prev_i);
...@@ -1419,14 +1508,14 @@ ModbusRTU::mbErrCode MBSlave::much_real_write( const ModbusRTU::ModbusData reg, ...@@ -1419,14 +1508,14 @@ ModbusRTU::mbErrCode MBSlave::much_real_write( const ModbusRTU::ModbusData reg,
return ModbusRTU::erNoError; return ModbusRTU::erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_write( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData val, const int fn ) ModbusRTU::mbErrCode MBSlave::real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData val, const int fn )
{ {
ModbusRTU::ModbusData dat[1] = {val}; ModbusRTU::ModbusData dat[1] = {val};
int i = 0; int i = 0;
return real_write(reg, dat, i, 1, fn); return real_write(rmap, reg, dat, i, 1, fn);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_write( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int& i, int count, const int fn ) ModbusRTU::mbErrCode MBSlave::real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int& i, int count, const int fn )
{ {
ModbusRTU::ModbusData mbval = dat[i]; ModbusRTU::ModbusData mbval = dat[i];
...@@ -1437,13 +1526,13 @@ ModbusRTU::mbErrCode MBSlave::real_write( const ModbusRTU::ModbusData reg, Modbu ...@@ -1437,13 +1526,13 @@ ModbusRTU::mbErrCode MBSlave::real_write( const ModbusRTU::ModbusData reg, Modbu
ModbusRTU::RegID regID = checkMBFunc ? genRegID(reg, fn) : genRegID(reg, default_mbfunc); ModbusRTU::RegID regID = checkMBFunc ? genRegID(reg, fn) : genRegID(reg, default_mbfunc);
auto it = iomap.find(regID); auto it = rmap.find(regID);
return real_write_it(it, dat, i, count); return real_write_it(rmap, it, dat, i, count);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_write_it( IOMap::iterator& it, ModbusRTU::ModbusData* dat, int& i, int count ) ModbusRTU::mbErrCode MBSlave::real_write_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData* dat, int& i, int count )
{ {
if( it == iomap.end() ) if( it == rmap.end() )
return ModbusRTU::erBadDataAddress; return ModbusRTU::erBadDataAddress;
IOProperty* p(&it->second); IOProperty* p(&it->second);
...@@ -1690,14 +1779,14 @@ ModbusRTU::mbErrCode MBSlave::real_write_prop( IOProperty* p, ModbusRTU::ModbusD ...@@ -1690,14 +1779,14 @@ ModbusRTU::mbErrCode MBSlave::real_write_prop( IOProperty* p, ModbusRTU::ModbusD
return ModbusRTU::erTimeOut; return ModbusRTU::erTimeOut;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::much_real_read( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, ModbusRTU::mbErrCode MBSlave::much_real_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat,
int count, const int fn ) int count, const int fn )
{ {
mbinfo << myname << "(much_real_read): read mbID=" mbinfo << myname << "(much_real_read): read mbID="
<< ModbusRTU::dat2str(reg) << "(" << (int)reg << ") " << " count=" << count << ModbusRTU::dat2str(reg) << "(" << (int)reg << ") " << " count=" << count
<< " mbfunc=" << fn << endl; << " mbfunc=" << fn << endl;
auto it = iomap.end(); auto it = rmap.end();
int i = 0; int i = 0;
int mbfunc = checkMBFunc ? fn : default_mbfunc; int mbfunc = checkMBFunc ? fn : default_mbfunc;
...@@ -1707,9 +1796,9 @@ ModbusRTU::mbErrCode MBSlave::much_real_read( const ModbusRTU::ModbusData reg, M ...@@ -1707,9 +1796,9 @@ ModbusRTU::mbErrCode MBSlave::much_real_read( const ModbusRTU::ModbusData reg, M
// ведь запросить могут начиная с "несуществующего регистра" // ведь запросить могут начиная с "несуществующего регистра"
for( ; i < count; i++ ) for( ; i < count; i++ )
{ {
it = iomap.find(regID + i); it = rmap.find(regID + i);
if( it != iomap.end() ) if( it != rmap.end() )
{ {
regID += i; regID += i;
break; break;
...@@ -1718,19 +1807,19 @@ ModbusRTU::mbErrCode MBSlave::much_real_read( const ModbusRTU::ModbusData reg, M ...@@ -1718,19 +1807,19 @@ ModbusRTU::mbErrCode MBSlave::much_real_read( const ModbusRTU::ModbusData reg, M
dat[i] = 0; dat[i] = 0;
} }
if( it == iomap.end() ) if( it == rmap.end() )
return ModbusRTU::erBadDataAddress; return ModbusRTU::erBadDataAddress;
ModbusRTU::ModbusData val = 0; ModbusRTU::ModbusData val = 0;
for( ; (it != iomap.end()) && (i < count); i++, regID++ ) for( ; (it != rmap.end()) && (i < count); i++, regID++ )
{ {
val = 0; val = 0;
// если регистры идут не подряд, то просто вернём ноль // если регистры идут не подряд, то просто вернём ноль
if( it->first == regID ) if( it->first == regID )
{ {
real_read_it(it, val); real_read_it(rmap, it, val);
++it; ++it;
} }
...@@ -1748,7 +1837,7 @@ ModbusRTU::mbErrCode MBSlave::much_real_read( const ModbusRTU::ModbusData reg, M ...@@ -1748,7 +1837,7 @@ ModbusRTU::mbErrCode MBSlave::much_real_read( const ModbusRTU::ModbusData reg, M
return ModbusRTU::erNoError; return ModbusRTU::erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_read( const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val, const int fn ) ModbusRTU::mbErrCode MBSlave::real_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val, const int fn )
{ {
ModbusRTU::RegID regID = checkMBFunc ? genRegID(reg, fn) : genRegID(reg, default_mbfunc); ModbusRTU::RegID regID = checkMBFunc ? genRegID(reg, fn) : genRegID(reg, default_mbfunc);
...@@ -1760,13 +1849,13 @@ ModbusRTU::mbErrCode MBSlave::real_read( const ModbusRTU::ModbusData reg, Modbus ...@@ -1760,13 +1849,13 @@ ModbusRTU::mbErrCode MBSlave::real_read( const ModbusRTU::ModbusData reg, Modbus
<< endl; << endl;
auto it = iomap.find(regID); auto it = rmap.find(regID);
return real_read_it(it, val); return real_read_it(rmap, it, val);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_read_it( IOMap::iterator& it, ModbusRTU::ModbusData& val ) ModbusRTU::mbErrCode MBSlave::real_read_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData& val )
{ {
if( it == iomap.end() ) if( it == rmap.end() )
return ModbusRTU::erBadDataAddress; return ModbusRTU::erBadDataAddress;
IOProperty* p(&it->second); IOProperty* p(&it->second);
...@@ -1950,10 +2039,17 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query, ReadInputRetMess ...@@ -1950,10 +2039,17 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query, ReadInputRetMess
{ {
mbinfo << myname << "(readInputRegisters): " << query << endl; mbinfo << myname << "(readInputRegisters): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(readInputRegisters): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
if( query.count <= 1 ) if( query.count <= 1 )
{ {
ModbusRTU::ModbusData d = 0; ModbusRTU::ModbusData d = 0;
ModbusRTU::mbErrCode ret = real_read(query.start, d, query.func); ModbusRTU::mbErrCode ret = real_read(regmap->second, query.start, d, query.func);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
reply.addData(d); reply.addData(d);
...@@ -1964,7 +2060,7 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query, ReadInputRetMess ...@@ -1964,7 +2060,7 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query, ReadInputRetMess
} }
// Фомирование ответа: // Фомирование ответа:
ModbusRTU::mbErrCode ret = much_real_read(query.start, buf, query.count, query.func); ModbusRTU::mbErrCode ret = much_real_read(regmap->second, query.start, buf, query.count, query.func);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
{ {
...@@ -2007,12 +2103,19 @@ ModbusRTU::mbErrCode MBSlave::readCoilStatus( ReadCoilMessage& query, ...@@ -2007,12 +2103,19 @@ ModbusRTU::mbErrCode MBSlave::readCoilStatus( ReadCoilMessage& query,
{ {
mbinfo << myname << "(readCoilStatus): " << query << endl; mbinfo << myname << "(readCoilStatus): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(readCoilStatus): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
try try
{ {
if( query.count <= 1 ) if( query.count <= 1 )
{ {
ModbusRTU::ModbusData d = 0; ModbusRTU::ModbusData d = 0;
ModbusRTU::mbErrCode ret = real_read(query.start, d, query.func); ModbusRTU::mbErrCode ret = real_read(regmap->second,query.start, d, query.func);
reply.addData(0); reply.addData(0);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
...@@ -2024,7 +2127,7 @@ ModbusRTU::mbErrCode MBSlave::readCoilStatus( ReadCoilMessage& query, ...@@ -2024,7 +2127,7 @@ ModbusRTU::mbErrCode MBSlave::readCoilStatus( ReadCoilMessage& query,
return ret; return ret;
} }
much_real_read(query.start, buf, query.count, query.func); much_real_read(regmap->second, query.start, buf, query.count, query.func);
int bnum = 0; int bnum = 0;
unsigned int i = 0; unsigned int i = 0;
...@@ -2072,12 +2175,19 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query, ...@@ -2072,12 +2175,19 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query,
{ {
mbinfo << myname << "(readInputStatus): " << query << endl; mbinfo << myname << "(readInputStatus): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(readInputStatus): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
try try
{ {
if( query.count <= 1 ) if( query.count <= 1 )
{ {
ModbusRTU::ModbusData d = 0; ModbusRTU::ModbusData d = 0;
ModbusRTU::mbErrCode ret = real_read(query.start, d, query.func); ModbusRTU::mbErrCode ret = real_read(regmap->second, query.start, d, query.func);
reply.addData(0); reply.addData(0);
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
...@@ -2089,7 +2199,7 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query, ...@@ -2089,7 +2199,7 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query,
return ret; return ret;
} }
much_real_read(query.start, buf, query.count, query.func); much_real_read(regmap->second, query.start, buf, query.count, query.func);
int bnum = 0; int bnum = 0;
unsigned int i = 0; unsigned int i = 0;
...@@ -2137,6 +2247,13 @@ ModbusRTU::mbErrCode MBSlave::forceMultipleCoils( ModbusRTU::ForceCoilsMessage& ...@@ -2137,6 +2247,13 @@ ModbusRTU::mbErrCode MBSlave::forceMultipleCoils( ModbusRTU::ForceCoilsMessage&
{ {
mbinfo << myname << "(forceMultipleCoils): " << query << endl; mbinfo << myname << "(forceMultipleCoils): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(forceMultipleCoils): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
ModbusRTU::mbErrCode ret = ModbusRTU::erNoError; ModbusRTU::mbErrCode ret = ModbusRTU::erNoError;
int nbit = 0; int nbit = 0;
...@@ -2149,7 +2266,7 @@ ModbusRTU::mbErrCode MBSlave::forceMultipleCoils( ModbusRTU::ForceCoilsMessage& ...@@ -2149,7 +2266,7 @@ ModbusRTU::mbErrCode MBSlave::forceMultipleCoils( ModbusRTU::ForceCoilsMessage&
for( auto k = 0; k < ModbusRTU::BitsPerByte && nbit < query.quant; k++, nbit++ ) for( auto k = 0; k < ModbusRTU::BitsPerByte && nbit < query.quant; k++, nbit++ )
{ {
// ModbusRTU::mbErrCode ret = // ModbusRTU::mbErrCode ret =
real_write(query.start + nbit, (b[k] ? 1 : 0), fn); real_write(regmap->second, query.start + nbit, (b[k] ? 1 : 0), fn);
//if( ret == ModbusRTU::erNoError ) //if( ret == ModbusRTU::erNoError )
} }
} }
...@@ -2166,8 +2283,15 @@ ModbusRTU::mbErrCode MBSlave::forceSingleCoil( ModbusRTU::ForceSingleCoilMessage ...@@ -2166,8 +2283,15 @@ ModbusRTU::mbErrCode MBSlave::forceSingleCoil( ModbusRTU::ForceSingleCoilMessage
{ {
mbinfo << myname << "(forceSingleCoil): " << query << endl; mbinfo << myname << "(forceSingleCoil): " << query << endl;
auto regmap = iomap.find(query.addr);
if( regmap == iomap.end() )
{
mbinfo << myname << "(forceSingleCoil): Unknown addr=" << ModbusRTU::addr2str(query.addr) << endl;
return ModbusRTU::erTimeOut;
}
int fn = getOptimizeWriteFunction(query.func); int fn = getOptimizeWriteFunction(query.func);
ModbusRTU::mbErrCode ret = real_write(query.start, (query.cmd() ? 1 : 0), fn ); ModbusRTU::mbErrCode ret = real_write(regmap->second, query.start, (query.cmd() ? 1 : 0), fn );
if( ret == ModbusRTU::erNoError ) if( ret == ModbusRTU::erNoError )
reply.set(query.start, query.data); reply.set(query.start, query.data);
...@@ -2254,7 +2378,7 @@ UniSetTypes::SimpleInfo* MBSlave::getInfo() ...@@ -2254,7 +2378,7 @@ UniSetTypes::SimpleInfo* MBSlave::getInfo()
inf << i->info << endl; inf << i->info << endl;
inf << vmon.pretty_str() << endl; inf << vmon.pretty_str() << endl;
inf << "LogServer: " << logserv_host << ":" << logserv_port << endl; inf << "LogServer: " << logserv_host << ":" << logserv_port << endl;
inf << " iomap=" << iomap.size() << endl; inf << "iomap=" << iomap.size() << " myaddr: " << ModbusServer::vaddr2str(vaddr) << endl;
inf << "Statistic: askCount=" << askCount << " pingOK=" << pingOK << endl; inf << "Statistic: askCount=" << askCount << " pingOK=" << pingOK << endl;
i->info = inf.str().c_str(); i->info = inf.str().c_str();
......
...@@ -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