Commit bd40cff6 authored by Pavel Vainerman's avatar Pavel Vainerman

Merge branch 'master' into devel/unet-priority

Conflicts: conf/libuniset2.spec extensions/UNetUDP/UNetReceiver.cc
parents bec1e9ef c1064d45
......@@ -32,9 +32,11 @@ Version 2.0
- uniset-codegen: дописать функцию help со всеми параметрами для _SK, тесты
- uniset-codegen: добавить в генерируемую документацию значения по умолчанию..
- uniset-codegen: добавить возможность переопределять привязку из командной строки
- unetudp: добавить возмоность привязать номера текущего посылаемого и принимаемого пакетов к датчику
- ModbusMaster: встроить возможность задать 'pulsar' (регистр сердцебиения)
- ТЕСТЫ! ТЕСТЫ! ТЕСТЫ!
......@@ -42,6 +44,8 @@ Version 2.0
uniset-codegen: добавить ключ --gen-sensor-name для генерирования name_Item.. (чтобы можно было в логах использовать текстовые названия)
SQL:
====
- добавить работу с History (при передаче указателя на SM в конструкторе).
......
......@@ -539,6 +539,7 @@ int omap()
{
if( !quiet )
cerr << "std::exception: " << ex.what() << endl;
return 1;
}
......@@ -600,6 +601,7 @@ int setValue( const string& args, UInterface& ui )
{
if( !quiet )
cerr << "std::exception: " << ex.what() << endl;
err = 1;
}
}
......@@ -666,6 +668,7 @@ int getValue( const string& args, UInterface& ui )
{
if( !quiet )
cerr << "std::exception: " << ex.what() << endl;
err = 1;
}
}
......@@ -714,6 +717,7 @@ int getCalibrate( const std::string& args, UInterface& ui )
{
if( !quiet )
cerr << "std::exception: " << ex.what() << endl;
err = 1;
}
}
......@@ -758,6 +762,7 @@ int getRawValue( const std::string& args, UInterface& ui )
{
if( !quiet )
cerr << "std::exception: " << ex.what() << endl;
err = 1;
}
}
......@@ -802,12 +807,14 @@ int getChangedTime( const std::string& args, UInterface& ui )
{
if( !quiet )
cerr << "CORBA::SystemException: " << ex.NP_minorString() << endl;
err = 1;
}
catch( const CORBA::Exception& )
{
if( !quiet )
cerr << "CORBA::Exception." << endl;
err = 1;
}
catch( const omniORB::fatalException& fe )
......@@ -819,20 +826,23 @@ int getChangedTime( const std::string& args, UInterface& ui )
cerr << " line: " << fe.line() << endl;
cerr << " mesg: " << fe.errmsg() << endl;
}
err = 1;
}
catch( const std::exception& ex )
{
if( !quiet )
cerr << "std::exception: " << ex.what() << endl;
err = 1;
}
catch(...)
{
if( !quiet )
cerr << "Unknown exception.." << endl;
err = 1;
}
}
}
return err;
......@@ -971,7 +981,7 @@ int oinfo( const string& args, UInterface& ui )
if( !quiet )
cerr << "Unknown exception.." << endl;
}
cout << endl << endl;
}
......
......@@ -25,11 +25,12 @@ print_usage()
}
#parse command line options
TEMP=`getopt -n $PROG -o h,d,c:,s: -l help,dump,confile:,watch_sec: -- "$@"` || exit 1
TEMP=`getopt -n $PROG -o h,d,c:,s: -l help,dump,confile:,watch_sec:,uniset-port: -- "$@"` || exit 1
eval set -- "$TEMP"
dump=
confile=
uport=
while :; do
case "$1" in
-h|--help) print_usage 0
......@@ -45,6 +46,10 @@ while :; do
shift
confile="$1"
;;
--uniset-port)
shift
uport="--uniset-port $1"
;;
--) shift; break
;;
*) "unrecognized option: $1"
......@@ -57,5 +62,5 @@ done
[ -n "$confile" ] && confile="--confile $confile"
[ -z "$dump" ] && $WATCH -n $WATCH_SEC uniset2-admin $confile --oinfo $*
[ -n "$dump" ] && uniset2-admin $confile --oinfo $*
[ -z "$dump" ] && $WATCH -n $WATCH_SEC uniset2-admin $confile --oinfo $* -- $uport
[ -n "$dump" ] && uniset2-admin $confile --oinfo $* -- $uport
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
#include <string>
#include <getopt.h>
#include "Debug.h"
......@@ -29,6 +28,7 @@ static struct option longopts[] =
{ "persistent-connection", no_argument, 0, 'o' },
{ "num-cycles", required_argument, 0, 'l' },
{ "sleep-msec", required_argument, 0, 's' },
{ "check", no_argument, 0, 'n' },
{ NULL, 0, 0, 0 }
};
......@@ -60,6 +60,7 @@ static void print_help()
printf("[-l|--num-cycles] num - Number of cycles of exchange. Default: -1 - infinitely.\n");
printf("[-v|--verbose] - Print all messages to stdout\n");
printf("[-s|--sleep-msec] - send pause. Default: 200 msec\n");
printf("[-n|--check] - Check connection for (-i)ip (-p)port\n");
}
// --------------------------------------------------------------------------
enum Command
......@@ -75,12 +76,11 @@ enum Command
cmdWrite06,
cmdWrite0F,
cmdWrite10,
cmdDiag
cmdDiag,
cmdCheck
};
// --------------------------------------------------------------------------
static char* checkArg( int ind, int argc, char* argv[] );
// --------------------------------------------------------------------------
int main( int argc, char** argv )
{
// std::ios::sync_with_stdio(false);
......@@ -121,7 +121,7 @@ int main( int argc, char** argv )
try
{
while( (opt = getopt_long(argc, argv, "hva:w:z:r:x:c:b:d:s:t:p:i:ol:d:e:u:", longopts, &optindex)) != -1 )
while( (opt = getopt_long(argc, argv, "hvna:w:z:r:x:c:b:d:s:t:p:i:ol:d:e:u:", longopts, &optindex)) != -1 )
{
switch (opt)
{
......@@ -137,6 +137,7 @@ int main( int argc, char** argv )
if( cmd == cmdNOP )
cmd = cmdRead02;
case 'r':
if( cmd == cmdNOP )
cmd = cmdRead03;
......@@ -162,6 +163,10 @@ int main( int argc, char** argv )
}
break;
case 'n':
cmd = cmdCheck;
break;
case 'e':
{
if( cmd == cmdNOP )
......@@ -602,6 +607,13 @@ int main( int argc, char** argv )
}
break;
case cmdCheck:
{
bool res = ModbusTCPMaster::checkConnection(iaddr, port, tout);
cout << iaddr << ":" << port << " connection " << (res ? "OK" : "FAIL") << endl;
}
break;
case cmdNOP:
default:
cerr << "No command. Use -h for help." << endl;
......@@ -662,3 +674,8 @@ char* checkArg( int i, int argc, char* argv[] )
return 0;
}
// --------------------------------------------------------------------------
void ping( const std::string& iaddr, int port )
{
cerr << "ping2: check connection " << ModbusTCPMaster::checkConnection(iaddr, port, 1000) << endl;
}
// --------------------------------------------------------------------------
......@@ -76,7 +76,6 @@ int main( int argc, char** argv )
int cmdonly = 0;
timeout_t tout = 0;
timeout_t rdelay = 5000;
bool cmdlist = false;
try
{
......@@ -140,7 +139,6 @@ int main( int argc, char** argv )
filter = string(arg2);
vcmd.push_back( LogReader::Command(LogServerTypes::cmdList, 0, filter) );
cmdlist = true;
}
break;
......@@ -239,15 +237,6 @@ int main( int argc, char** argv )
lr.setinTimeout(tout);
lr.setReconnectDelay(rdelay);
/*
if( cmdlist && vcmd.size() == 1 )
{
cmdonly = 1;
lr.setReadCount(1);
lr.sendCommand(addr, port, vcmd, cmdonly, verb);
return 0;
}
*/
if( !vcmd.empty() )
lr.sendCommand(addr, port, vcmd, cmdonly, verb);
......
......@@ -13,7 +13,7 @@
Name: libuniset2
Version: 2.1
Release: alt15.1
Release: alt25
Summary: UniSet - library for building distributed industrial control systems
......@@ -456,6 +456,50 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# ..
%changelog
* Mon Sep 14 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt25
- (PassiveTimer): fixed bug in default init
- (Pulse): refactoring
* Thu Sep 10 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt24
- (LogServer): refactoring (more use shared_ptr)
* Mon Sep 07 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt23
- (ModbusPersistentSlave): fixed bug in end connection processing
- (uniset-log): fixed bug in end connection processing
* Sun Sep 06 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt22
- refactoring (use shared_ptr), change pollfactor realisation..
* Sat Sep 05 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt21
- (modbus slave): add more logs..
* Sat Aug 29 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt20
- (ModbusSession): add setKeepAliveParams()
* Sat Aug 29 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt19
- (ModbusSlave): rename ModbusMultiSlave --> ModbusPersistentSlave, minor fixes
* Thu Aug 27 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt18
- (ModbusExchange): add reinit_timeout timer..
* Fri Aug 21 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt17
- up build
* Fri Aug 21 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt16.2
- (ModbusTCP): fixed bug in update respond sensor in SharedMemory
* Thu Aug 20 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt16.1
- (ModbusTCP): add more vmonit parameters
* Thu Aug 20 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt16
- (modbustcptest): add 'check' for connection
* Tue Aug 18 2015 Pavel Vainerman <pv@altlinux.ru> 2.1-alt15.3
- minor build
* Fri Aug 14 2015 Pavel Vainerman <pv@etersoft.ru> 2.1-alt15.2
- up build
* Thu Aug 13 2015 Pavel Vainerman <pv@etersoft.ru> 2.1-alt15.1
- test build for new UNetUDP
......
......@@ -78,9 +78,9 @@
<item addr="0x01" invert="0" respondSensor="RespondRTU_S" timeout="5000" modeSensor="MB1_Mode_AS"/>
</DeviceList>
</MBMaster1>
<MBMultiMaster1 levels="info,warn,crit" name="MBMaster1" poll_time="200" reply_timeout="60">
<MBMultiMaster1 levels="info,warn,crit" name="MBMaster1" polltime="200">
<DeviceList>
<item addr="0x01" invert="0" respondSensor="RespondRTU_S" timeout="5000" modeSensor="MB1_Mode_AS"/>
<item addr="0x01" invert="1" force="0" respondSensor="RespondRTU_S" timeout="1000" modeSensor="MB1_Mode_AS"/>
</DeviceList>
<GateList>
<item ip="localhost" port="2048" recv_timeout="800" invert="1" respondSensor="MM1_Not_Respond_S"/>
......
......@@ -4,7 +4,7 @@
#include <ostream>
#include <string>
#include <map>
#include <vector>
#include <unordered_map>
#include <memory>
#include "IONotifyController.h"
#include "UniSetObject_LT.h"
......@@ -84,7 +84,7 @@ class MBExchange:
RSProperty():
nbit(-1), vType(VTypes::vtUnknown),
rnum(VTypes::wsize(VTypes::vtUnknown)),
nbyte(0), reg(0)
nbyte(0)
{}
// т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
......@@ -94,7 +94,7 @@ class MBExchange:
RSProperty( RSProperty&& r ) = default;
RSProperty& operator=(RSProperty&& r) = default;
RegInfo* reg;
std::shared_ptr<RegInfo> reg;
};
friend std::ostream& operator<<( std::ostream& os, const RSProperty& p );
......@@ -102,7 +102,7 @@ class MBExchange:
typedef std::list<RSProperty> PList;
static std::ostream& print_plist( std::ostream& os, const PList& p );
typedef std::map<ModbusRTU::RegID, RegInfo*> RegMap;
typedef std::map<ModbusRTU::RegID, std::shared_ptr<RegInfo>> RegMap;
struct RegInfo
{
// т.к. RSProperty содержит rwmutex с запрещённым конструктором копирования
......@@ -126,7 +126,7 @@ class MBExchange:
PList slst;
ModbusRTU::RegID id;
RTUDevice* dev;
std::shared_ptr<RTUDevice> dev;
// only for RTU188
RTUStorage::RTUJack rtuJack;
......@@ -151,11 +151,6 @@ class MBExchange:
// Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
// ещё не инициализировано из SM
bool sm_initOK; /*!< инициализировалось ли значение из SM */
/*! приоритет опроса, 0,1 - высший,
* 1...n - задаёт "часоту" опроса. Т.е. каждые 1...n циклов
*/
int pollfactor = { 0 };
};
friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
......@@ -164,7 +159,6 @@ class MBExchange:
struct RTUDevice
{
RTUDevice():
respnond(false),
mbaddr(0),
dtype(dtUnknown),
resp_id(UniSetTypes::DefaultObjectId),
......@@ -176,13 +170,12 @@ class MBExchange:
mode_id(UniSetTypes::DefaultObjectId),
mode(emNone),
speed(ComPort::ComSpeed38400),
rtu(0)
rtu188(0)
{
}
bool respnond;
ModbusRTU::ModbusAddr mbaddr; /*!< адрес устройства */
RegMap regmap;
std::unordered_map<unsigned int, std::shared_ptr<RegMap>> pollmap;
DeviceType dtype; /*!< тип устройства */
......@@ -210,12 +203,14 @@ class MBExchange:
// специфические поля для RS
ComPort::Speed speed;
RTUStorage* rtu;
std::shared_ptr<RTUStorage> rtu188;
std::string getShortInfo() const;
};
friend std::ostream& operator<<( std::ostream& os, RTUDevice& d );
typedef std::map<ModbusRTU::ModbusAddr, RTUDevice*> RTUDeviceMap;
typedef std::map<ModbusRTU::ModbusAddr, std::shared_ptr<RTUDevice>> RTUDeviceMap;
friend std::ostream& operator<<( std::ostream& os, RTUDeviceMap& d );
void printMap(RTUDeviceMap& d);
......@@ -256,14 +251,14 @@ class MBExchange:
InitRegInfo():
dev(0), mbreg(0),
mbfunc(ModbusRTU::fnUnknown),
initOK(false), ri(0)
initOK(false)
{}
RSProperty p;
RTUDevice* dev;
std::shared_ptr<RTUDevice> dev;
ModbusRTU::ModbusData mbreg;
ModbusRTU::SlaveFunctionCode mbfunc;
bool initOK;
RegInfo* ri;
std::shared_ptr<RegInfo> ri;
};
typedef std::list<InitRegInfo> InitList;
......@@ -272,14 +267,14 @@ class MBExchange:
bool initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p );
bool allInitOK;
RTUDeviceMap rmap;
RTUDeviceMap devices;
InitList initRegList; /*!< список регистров для инициализации */
UniSetTypes::uniset_rwmutex pollMutex;
virtual std::shared_ptr<ModbusClient> initMB( bool reopen = false ) = 0;
virtual bool poll();
bool pollRTU( RTUDevice* dev, RegMap::iterator& it );
bool pollRTU( std::shared_ptr<RTUDevice>& dev, RegMap::iterator& it );
void updateSM();
void updateRTU(RegMap::iterator& it);
......@@ -301,15 +296,15 @@ class MBExchange:
void initDeviceList();
void initOffsetList();
RTUDevice* addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
RegInfo* addReg( RegMap& rmap, ModbusRTU::RegID id, ModbusRTU::ModbusData r, UniXML::iterator& it, RTUDevice* dev );
std::shared_ptr<RTUDevice> addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
std::shared_ptr<RegInfo> addReg(std::shared_ptr<RegMap>& devices, ModbusRTU::RegID id, ModbusRTU::ModbusData r, UniXML::iterator& it, std::shared_ptr<RTUDevice> dev );
RSProperty* addProp( PList& plist, RSProperty&& p );
bool initMTRitem( UniXML::iterator& it, RegInfo* p );
bool initRTU188item( UniXML::iterator& it, RegInfo* p );
bool initMTRitem(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
bool initRTU188item(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
bool initRSProperty( RSProperty& p, UniXML::iterator& it );
bool initRegInfo( RegInfo* r, UniXML::iterator& it, RTUDevice* dev );
bool initRTUDevice( RTUDevice* d, UniXML::iterator& it );
bool initRegInfo(std::shared_ptr<RegInfo>& r, UniXML::iterator& it, std::shared_ptr<RTUDevice>& dev );
bool initRTUDevice( std::shared_ptr<RTUDevice>& d, UniXML::iterator& it );
virtual bool initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
std::string initPropPrefix( const std::string& def_prop_prefix = "" );
......@@ -366,6 +361,8 @@ class MBExchange:
PassiveTimer ptReopen; /*!< таймер для переоткрытия соединения */
Trigger trReopen;
PassiveTimer ptInitChannel; /*!< таймер не реинициализацию канала связи */
// т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
// и отдельно его проверяем потом
typedef std::list<IOBase> ThresholdList;
......
......@@ -48,7 +48,7 @@ MBTCPMaster::MBTCPMaster( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shm
if( shm->isLocalwork() )
{
readConfiguration();
rtuQueryOptimization(rmap);
rtuQueryOptimization(devices);
initDeviceList();
}
else
......@@ -58,7 +58,7 @@ MBTCPMaster::MBTCPMaster( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shm
pollThread->setFinalAction(this, &MBTCPMaster::final_thread);
if( mblog->is_info() )
printMap(rmap);
printMap(devices);
}
// -----------------------------------------------------------------------------
MBTCPMaster::~MBTCPMaster()
......@@ -81,6 +81,7 @@ std::shared_ptr<ModbusClient> MBTCPMaster::initMB( bool reopen )
mbtcp.reset();
mb.reset();
ptInitChannel.reset();
}
try
......@@ -252,7 +253,7 @@ UniSetTypes::SimpleInfo* MBTCPMaster::getInfo()
ostringstream inf;
inf << i->info << endl;
inf << "poll: " << iaddr << ":" << port << endl;
inf << "poll: " << iaddr << ":" << port << " pesrsistent-connection=" << ( force_disconnect ? "NO" : "YES" ) << endl;
i->info = inf.str().c_str();
return i._retn();
......
......@@ -69,6 +69,9 @@
(после этого идёт попытка реинициализировать соединение)
По умолчанию 5000 мсек.
\b --xxx-reinit-timeout или \b reinit_timeout msec - таймаут на реинициализацию канала связи (после потери связи)
По умолчанию timeout.
\b --xxx-no-query-optimization или \b no_query_optimization - [1|0] отключить оптимизацию запросов
Оптимизация заключается в том, что регистры идущие подряд автоматически запрашиваются/записываются одним запросом.
......
......@@ -128,7 +128,7 @@ MBTCPMultiMaster::MBTCPMultiMaster( UniSetTypes::ObjectId objId, UniSetTypes::Ob
if( shm->isLocalwork() )
{
readConfiguration();
rtuQueryOptimization(rmap);
rtuQueryOptimization(devices);
initDeviceList();
}
else
......@@ -145,7 +145,7 @@ MBTCPMultiMaster::MBTCPMultiMaster( UniSetTypes::ObjectId objId, UniSetTypes::Ob
ptReopen.setTiming(default_timeout);
if( mblog->is_info() )
printMap(rmap);
printMap(devices);
}
// -----------------------------------------------------------------------------
MBTCPMultiMaster::~MBTCPMultiMaster()
......@@ -171,6 +171,9 @@ MBTCPMultiMaster::~MBTCPMultiMaster()
// -----------------------------------------------------------------------------
std::shared_ptr<ModbusClient> MBTCPMultiMaster::initMB( bool reopen )
{
if( mb )
ptInitChannel.reset();
// просто движемся по кругу (т.к. связь не проверяется)
// движемся в обратном порядке, т.к. сортировка по возрастанию приоритета
if( checktime <= 0 )
......@@ -363,17 +366,16 @@ void MBTCPMultiMaster::check_thread()
{
try
{
if( it->use ) // игнорируем текущий mbtcp
continue;
// Если use=1" связь не проверяем и считаем что связь есть..
bool r = ( it->use ? true : it->check() );
bool r = it->check();
mbinfo << myname << "(check): " << it->myname << " " << ( r ? "OK" : "FAIL" ) << endl;
mblog4 << myname << "(check): " << it->myname << " " << ( r ? "OK" : "FAIL" ) << endl;
try
{
if( it->respond_id != DefaultObjectId && (it->respond_force || !it->respond_init || r != it->respond) )
{
bool set = it->respond_invert ? !it->respond : it->respond;
bool set = it->respond_invert ? !r : r;
shm->localSetValue(it->respond_it, it->respond_id, (set ? 1 : 0), getId());
it->respond_init = true;
}
......@@ -413,7 +415,7 @@ void MBTCPMultiMaster::initIterators()
{
MBExchange::initIterators();
for( auto& it : mblist )
for( auto && it : mblist )
shm->initIterator(it.respond_it);
}
// -----------------------------------------------------------------------------
......@@ -497,7 +499,13 @@ std::shared_ptr<MBTCPMultiMaster> MBTCPMultiMaster::init_mbmaster( int argc, con
const std::string MBTCPMultiMaster::MBSlaveInfo::getShortInfo() const
{
ostringstream s;
s << myname << " respond=" << respond;
s << myname << " respond=" << respond
<< " (respond_id=" << respond_id << " respond_invert=" << respond_invert
<< " recv_timeout=" << recv_timeout << " resp_force=" << respond_force
<< " use=" << use << " ignore=" << ignore << " priority=" << priority
<< " persistent-connection=" << !force_disconnect
<< ")";
return std::move(s.str());
}
// -----------------------------------------------------------------------------
......@@ -508,7 +516,7 @@ UniSetTypes::SimpleInfo* MBTCPMultiMaster::getInfo()
ostringstream inf;
inf << i->info << endl;
inf << "Gates: " << endl;
inf << "Gates: " << (checktime <= 0 ? "/ check connections DISABLED /" : "") << endl;
for( const auto& m : mblist )
inf << " " << m.getShortInfo() << endl;
......
......@@ -87,6 +87,9 @@
(после этого идёт попытка реинициализировать соединение)
По умолчанию 5000 мсек.
\b --xxx-reinit-timeout или \b reinit_timeout msec - таймаут на реинициализацию канала связи (после потери связи)
По умолчанию timeout мсек.
\b --xxx-no-query-optimization или \b no_query_optimization - [1|0] отключить оптимизацию запросов
Оптимизация заключается в том, что регистры идущие подряд автоматически запрашиваются/записываются одним запросом.
......@@ -280,6 +283,7 @@ class MBTCPMultiMaster:
bool check();
inline void setUse( bool st )
{
respond_init = !( st && !use );
use = st;
}
......
......@@ -70,7 +70,7 @@ RTUExchange::RTUExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shm
if( shm->isLocalwork() )
{
readConfiguration();
rtuQueryOptimization(rmap);
rtuQueryOptimization(devices);
initDeviceList();
}
else
......@@ -79,7 +79,7 @@ RTUExchange::RTUExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shm
initMB(false);
if( dlog()->is_info() )
printMap(rmap);
printMap(devices);
}
// -----------------------------------------------------------------------------
void RTUExchange::help_print( int argc, const char* const* argv )
......@@ -204,9 +204,9 @@ bool RTUExchange::poll()
bool allNotRespond = true;
ComPort::Speed s = mbrtu->getSpeed();
for( auto it1 : rmap )
for( auto it1 : devices )
{
RTUDevice* d(it1.second);
auto d = it1.second;
if( d->mode_id != DefaultObjectId && d->mode == emSkipExchange )
continue;
......@@ -221,7 +221,7 @@ bool RTUExchange::poll()
if( d->dtype == MBExchange::dtRTU188 )
{
if( !d->rtu )
if( !d->rtu188 )
continue;
dlog3 << myname << "(pollRTU188): poll RTU188 "
......@@ -233,7 +233,7 @@ bool RTUExchange::poll()
if( rs_pre_clean )
mb->cleanupChannel();
d->rtu->poll(mbrtu);
d->rtu188->poll(mbrtu);
d->numreply++;
allNotRespond = false;
}
......@@ -249,38 +249,46 @@ bool RTUExchange::poll()
else
{
dlog3 << myname << "(poll): ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " regs=" << d->regmap.size() << endl;
<< " regs=" << d->pollmap.size() << endl;
for( auto it = d->regmap.begin(); it != d->regmap.end(); ++it )
for( auto&& m: d->pollmap )
{
try
if( m.first!=0 && (ncycle % m.first) != 0 )
continue;
auto rmap = m.second;
for( auto&& it = rmap->begin(); it != rmap->end(); ++it )
{
if( d->dtype == RTUExchange::dtRTU || d->dtype == RTUExchange::dtMTR )
try
{
if( rs_pre_clean )
mb->cleanupChannel();
if( pollRTU(d, it) )
if( d->dtype == RTUExchange::dtRTU || d->dtype == RTUExchange::dtMTR )
{
d->numreply++;
allNotRespond = false;
if( rs_pre_clean )
mb->cleanupChannel();
if( pollRTU(d, it) )
{
d->numreply++;
allNotRespond = false;
}
}
}
}
catch( ModbusRTU::mbException& ex )
{
dlog3 << myname << "(poll): FAILED ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " reg=" << ModbusRTU::dat2str(it->second->mbreg)
<< " for sensors: ";
print_plist(dlog()->level3(), it->second->slst);
dlog()->level3() << " err: " << ex << endl;
}
catch( ModbusRTU::mbException& ex )
{
dlog3 << myname << "(poll): FAILED ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " reg=" << ModbusRTU::dat2str(it->second->mbreg)
<< " for sensors: ";
print_plist(dlog()->level3(), it->second->slst);
dlog()->level3() << " err: " << ex << endl;
}
if( it == d->regmap.end() )
break;
if( it == rmap->end() )
break;
if( !checkProcActive() )
return false;
if( !checkProcActive() )
return false;
}
}
}
}
......
......@@ -8,11 +8,13 @@
--mbtcp-set-prop-prefix \
--mbtcp-filter-field rs \
--mbtcp-filter-value 5 \
--mbtcp-recv-timeout 1000 \
--mbtcp-recv-timeout 7000 \
--mbtcp-timeout 2000 \
--mbtcp-polltime 1000 \
--mbtcp-polltime 2000 \
--mbtcp-force-out 1 \
--mbtcp-log-add-levels any \
--mbtcp-persistent-connection 1 \
--mbtcp-run-logserver \
$*
#--mbtcp-exchange-mode-id MB1_Mode_AS \
......
......@@ -559,7 +559,7 @@ void MBSlave::execute_rtu()
}
}
for( auto& it : iomap )
for( auto && it : iomap )
IOBase::processingThreshold(&it.second, shm, force);
}
catch(...) {}
......@@ -645,7 +645,7 @@ void MBSlave::execute_tcp()
}
}
for( auto& it : iomap )
for( auto && it : iomap )
IOBase::processingThreshold(&it.second, shm, force);
}
catch( const std::exception& ex )
......@@ -759,9 +759,9 @@ void MBSlave::askSensors( UniversalIO::UIOCommand cmd )
if( force )
return;
for( auto& it : iomap )
for( const auto& it : iomap )
{
IOProperty* p(&it.second);
const IOProperty* p(&it.second);
try
{
......@@ -1147,7 +1147,7 @@ int MBSlave::getOptimizeWriteFunction( const int fn )
// ------------------------------------------------------------------------------------------
bool MBSlave::BitRegProperty::check( const IOController_i::SensorInfo& si )
{
for( auto& i : bvec )
for( const auto& i : bvec )
{
if( i.si.id == si.id && i.si.node == si.node )
return true;
......@@ -1267,7 +1267,7 @@ std::ostream& operator<<( std::ostream& os, MBSlave::BitRegProperty& p )
{
os << " reg=" << ModbusRTU::dat2str(p.mbreg) << "(" << (int)p.mbreg << ")[ ";
for( auto& i : p.bvec )
for( const auto& i : p.bvec )
os << "'" << i.si.id << "' ";
os << "]";
......@@ -1906,36 +1906,39 @@ ModbusRTU::mbErrCode MBSlave::real_read_prop( IOProperty* p, ModbusRTU::ModbusDa
else
return ModbusRTU::erBadDataAddress;
mblog3 << myname << "(real_read_prop): read OK. sid=" << p->si.id << " val=" << val << endl;
pingOK = true;
return ModbusRTU::erNoError;
}
catch( UniSetTypes::NameNotFound& ex )
{
mbwarn << myname << "(real_read_it): " << ex << endl;
mbwarn << myname << "(real_read_prop): " << ex << endl;
return ModbusRTU::erBadDataAddress;
}
catch( UniSetTypes::OutOfRange& ex )
{
mbwarn << myname << "(real_read_it): " << ex << endl;
mbwarn << myname << "(real_read_prop): " << ex << endl;
return ModbusRTU::erBadDataValue;
}
catch( const Exception& ex )
{
if( pingOK )
mbcrit << myname << "(real_read_it): " << ex << endl;
mbcrit << myname << "(real_read_prop): " << ex << endl;
}
catch( const CORBA::SystemException& ex )
{
if( pingOK )
mbcrit << myname << "(real_read_it): CORBA::SystemException: "
mbcrit << myname << "(real_read_prop): CORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch(...)
{
if( pingOK )
mbcrit << myname << "(real_read_it) catch ..." << endl;
mbcrit << myname << "(real_read_prop) catch ..." << endl;
}
mbwarn << myname << "(real_read_prop): read sid=" << p->si.id << " FAILED!!" << endl;
pingOK = false;
return ModbusRTU::erTimeOut;
}
......@@ -2249,6 +2252,8 @@ UniSetTypes::SimpleInfo* MBSlave::getInfo()
inf << i->info << endl;
inf << vmon.pretty_str() << endl;
inf << "LogServer: " << logserv_host << ":" << logserv_port << endl;
inf << " iomap=" << iomap.size() << endl;
inf << "Statistic: askCount=" << askCount << " pingOK=" << pingOK << endl;
i->info = inf.str().c_str();
return i._retn();
......
......@@ -2,7 +2,7 @@
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "MBTCPMultiSlave.h"
#include "MBTCPPersistentSlave.h"
#include "modbus/ModbusRTUSlaveSlot.h"
#include "modbus/ModbusTCPServerSlot.h"
#include "modbus/MBLogSugar.h"
......@@ -12,7 +12,7 @@ using namespace UniSetTypes;
using namespace UniSetExtensions;
using namespace ModbusRTU;
// -----------------------------------------------------------------------------
MBTCPMultiSlave::MBTCPMultiSlave( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const std::shared_ptr<SharedMemory> ic, const string& prefix ):
MBTCPPersistentSlave::MBTCPPersistentSlave( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const std::shared_ptr<SharedMemory> ic, const string& prefix ):
MBSlave(objId, shmId, ic, prefix),
sesscount_id(DefaultObjectId)
{
......@@ -22,7 +22,7 @@ MBTCPMultiSlave::MBTCPMultiSlave( UniSetTypes::ObjectId objId, UniSetTypes::Obje
cnode = conf->getNode(conf_name);
if( cnode == NULL )
throw UniSetTypes::SystemError("(MBTCPMultiSlave): Not found conf-node for " + myname );
throw UniSetTypes::SystemError("(MBTCPPersistentSlave): Not found conf-node for " + myname );
UniXML::iterator it(cnode);
......@@ -31,18 +31,20 @@ MBTCPMultiSlave::MBTCPMultiSlave( UniSetTypes::ObjectId objId, UniSetTypes::Obje
if( waitTimeout == 0 )
waitTimeout = 4000;
ptUpdateInfo.setTiming(waitTimeout);
vmonit(waitTimeout);
sessTimeout = conf->getArgInt("--" + prefix + "-session-timeout", it.getProp("sessTimeout"));
if( sessTimeout == 0 )
sessTimeout = 10000;
sessTimeout = 2000;
vmonit(sessTimeout);
sessMaxNum = conf->getArgInt("--" + prefix + "-session-maxnum", it.getProp("sessMaxNum"));
if( sessMaxNum == 0 )
sessMaxNum = 10;
sessMaxNum = 3;
vmonit(sessMaxNum);
......@@ -109,11 +111,11 @@ MBTCPMultiSlave::MBTCPMultiSlave( UniSetTypes::ObjectId objId, UniSetTypes::Obje
}
}
// -----------------------------------------------------------------------------
MBTCPMultiSlave::~MBTCPMultiSlave()
MBTCPPersistentSlave::~MBTCPPersistentSlave()
{
}
// -----------------------------------------------------------------------------
void MBTCPMultiSlave::help_print( int argc, const char* const* argv )
void MBTCPPersistentSlave::help_print( int argc, const char* const* argv )
{
MBSlave::help_print(argc, argv);
......@@ -124,7 +126,7 @@ void MBTCPMultiSlave::help_print( int argc, const char* const* argv )
cout << "--prefix-session-count-id id - Датчик для отслеживания текущего количества соединений." << endl;
}
// -----------------------------------------------------------------------------
std::shared_ptr<MBTCPMultiSlave> MBTCPMultiSlave::init_mbslave( int argc, const char* const* argv, UniSetTypes::ObjectId icID,
std::shared_ptr<MBTCPPersistentSlave> MBTCPPersistentSlave::init_mbslave( int argc, const char* const* argv, UniSetTypes::ObjectId icID,
const std::shared_ptr<SharedMemory> ic, const string& prefix )
{
auto conf = uniset_conf();
......@@ -147,10 +149,10 @@ std::shared_ptr<MBTCPMultiSlave> MBTCPMultiSlave::init_mbslave( int argc, const
}
dinfo << "(mbslave): name = " << name << "(" << ID << ")" << endl;
return make_shared<MBTCPMultiSlave>(ID, icID, ic, prefix);
return make_shared<MBTCPPersistentSlave>(ID, icID, ic, prefix);
}
// -----------------------------------------------------------------------------
void MBTCPMultiSlave::execute_tcp()
void MBTCPPersistentSlave::execute_tcp()
{
auto sslot = dynamic_pointer_cast<ModbusTCPServerSlot>(mbslot);
......@@ -177,6 +179,13 @@ void MBTCPMultiSlave::execute_tcp()
{
sslot->waitQuery( addr, waitTimeout );
// если слишком быстро обработали запрос
// то ничего не делаем..
if( !ptUpdateInfo.checkTime() )
continue;
ptUpdateInfo.reset();
// Обновляем информацию по соединениям
sess.clear();
sslot->getSessions(sess);
......@@ -318,7 +327,7 @@ void MBTCPMultiSlave::execute_tcp()
mbinfo << myname << "(execute_tcp): thread stopped.." << endl;
}
// -----------------------------------------------------------------------------
void MBTCPMultiSlave::initIterators()
void MBTCPPersistentSlave::initIterators()
{
MBSlave::initIterators();
......@@ -328,7 +337,7 @@ void MBTCPMultiSlave::initIterators()
i.second.initIterators(shm);
}
// -----------------------------------------------------------------------------
bool MBTCPMultiSlave::deactivateObject()
bool MBTCPPersistentSlave::deactivateObject()
{
if( mbslot )
{
......@@ -341,7 +350,7 @@ bool MBTCPMultiSlave::deactivateObject()
return MBSlave::deactivateObject();
}
// -----------------------------------------------------------------------------
void MBTCPMultiSlave::sigterm( int signo )
void MBTCPPersistentSlave::sigterm( int signo )
{
if( mbslot )
{
......@@ -354,7 +363,7 @@ void MBTCPMultiSlave::sigterm( int signo )
MBSlave::sigterm(signo);
}
// -----------------------------------------------------------------------------
const std::string MBTCPMultiSlave::ClientInfo::getShortInfo() const
const std::string MBTCPPersistentSlave::ClientInfo::getShortInfo() const
{
ostringstream s;
......@@ -363,7 +372,7 @@ const std::string MBTCPMultiSlave::ClientInfo::getShortInfo() const
return std::move(s.str());
}
// -----------------------------------------------------------------------------
UniSetTypes::SimpleInfo* MBTCPMultiSlave::getInfo()
UniSetTypes::SimpleInfo* MBTCPPersistentSlave::getInfo()
{
UniSetTypes::SimpleInfo_var i = MBSlave::getInfo();
......
// -----------------------------------------------------------------------------
#ifndef _MBTCPMultiSlave_H_
#define _MBTCPMultiSlave_H_
#ifndef _MBTCPPersistentSlave_H_
#define _MBTCPPersistentSlave_H_
// -----------------------------------------------------------------------------
#include <unordered_map>
#include "MBSlave.h"
#include "modbus/ModbusTCPServer.h"
// -----------------------------------------------------------------------------
/*!
<MBTCPMultiSlave ....sesscount="">
<MBTCPPersistentSlave ....sesscount="">
<clients>
<item ip="" respond="" invert="1" askcount=""/>
<item ip="" respond="" invert="1" askcount=""/>
<item ip="" respond="" invert="1" askcount=""/>
</clients>
</MBTCPMultiSlave>
</MBTCPPersistentSlave>
*/
// -----------------------------------------------------------------------------
/*! Реализация многоптоточного slave-интерфейса */
class MBTCPMultiSlave:
class MBTCPPersistentSlave:
public MBSlave
{
public:
MBTCPMultiSlave( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, const std::shared_ptr<SharedMemory> ic = nullptr, const std::string& prefix = "mbs" );
virtual ~MBTCPMultiSlave();
MBTCPPersistentSlave( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, const std::shared_ptr<SharedMemory> ic = nullptr, const std::string& prefix = "mbs" );
virtual ~MBTCPPersistentSlave();
/*! глобальная функция для инициализации объекта */
static std::shared_ptr<MBTCPMultiSlave> init_mbslave( int argc, const char* const* argv,
static std::shared_ptr<MBTCPPersistentSlave> init_mbslave( int argc, const char* const* argv,
UniSetTypes::ObjectId shmID, const std::shared_ptr<SharedMemory> ic = nullptr,
const std::string& prefix = "mbs" );
......@@ -44,6 +44,7 @@ class MBTCPMultiSlave:
timeout_t waitTimeout;
ModbusTCPServer::Sessions sess; /*!< список открытых сессий */
unsigned int sessMaxNum;
PassiveTimer ptUpdateInfo;
struct ClientInfo
{
......@@ -82,5 +83,5 @@ class MBTCPMultiSlave:
IOController::IOStateList::iterator sesscount_it;
};
// -----------------------------------------------------------------------------
#endif // _MBTCPMultiSlave_H_
#endif // _MBTCPPersistentSlave_H_
// -----------------------------------------------------------------------------
bin_PROGRAMS = @PACKAGE@-mbslave @PACKAGE@-mbtcp-multislave
bin_PROGRAMS = @PACKAGE@-mbslave @PACKAGE@-mbtcp-persistentslave
# не забывайте править версию в2.pc-файле
UMBS_VER=@LIBVER@
......@@ -10,7 +10,7 @@ libUniSet2MBSlave_la_LIBADD = $(top_builddir)/lib/libUniSet2.la \
$(top_builddir)/extensions/lib/libUniSet2Extensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
libUniSet2MBSlave_la_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libUniSet2MBSlave_la_SOURCES = MBSlave.cc MBTCPMultiSlave.cc
libUniSet2MBSlave_la_SOURCES = MBSlave.cc MBTCPPersistentSlave.cc
@PACKAGE@_mbslave_SOURCES = mbslave.cc
@PACKAGE@_mbslave_LDADD = libUniSet2MBSlave.la $(top_builddir)/lib/libUniSet2.la \
......@@ -19,12 +19,12 @@ libUniSet2MBSlave_la_SOURCES = MBSlave.cc MBTCPMultiSlave.cc
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_mbslave_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_mbtcp_multislave_SOURCES = mbtcp-multislave.cc
@PACKAGE@_mbtcp_multislave_LDADD = libUniSet2MBSlave.la $(top_builddir)/lib/libUniSet2.la \
@PACKAGE@_mbtcp_persistentslave_SOURCES = mbtcp-persistentslave.cc
@PACKAGE@_mbtcp_persistentslave_LDADD = libUniSet2MBSlave.la $(top_builddir)/lib/libUniSet2.la \
$(top_builddir)/extensions/SharedMemory/libUniSet2SharedMemory.la \
$(top_builddir)/extensions/lib/libUniSet2Extensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_mbtcp_multislave_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_mbtcp_persistentslave_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
# install
devel_include_HEADERS = *.h
......
......@@ -2,7 +2,7 @@
#include <sstream>
#include <string>
#include <cc++/socket.h>
#include "MBTCPMultiSlave.h"
#include "MBTCPPersistentSlave.h"
#include "Configuration.h"
#include "Debug.h"
#include "UniSetActivator.h"
......@@ -56,7 +56,7 @@ int main(int argc, const char** argv)
return 1;
}
auto s = MBTCPMultiSlave::init_mbslave(argc, argv, shmID);
auto s = MBTCPPersistentSlave::init_mbslave(argc, argv, shmID);
if( !s )
{
......@@ -70,9 +70,9 @@ int main(int argc, const char** argv)
act->broadcast( sm.transport_msg() );
ulogany << "\n\n\n";
ulogany << "(main): -------------- MBTCPMultiSlave START -------------------------\n\n";
ulogany << "(main): -------------- MBTCPPersistentSlave START -------------------------\n\n";
dlogany << "\n\n\n";
dlogany << "(main): -------------- MBTCPMultiSlave START -------------------------\n\n";
dlogany << "(main): -------------- MBTCPPersistentSlave START -------------------------\n\n";
act->run(false);
return 0;
......
#!/bin/sh
uniset2-start.sh -f ./uniset2-mbtcp-multislave --confile test.xml --dlog-add-levels level3,level4 \
uniset2-start.sh -f ./uniset2-mbtcp-persistentslave --confile test.xml --dlog-add-levels level3,level4 \
--smemory-id SharedMemory \
--mbs-name MBMultiSlave1 --mbs-type TCP --mbs-inet-addr 127.0.0.1 --mbs-inet-port 2048 --mbs-reg-from-id 1 --mbs-my-addr 0x01 \
$*
......
......@@ -289,7 +289,7 @@ bool SharedMemory::activateObject()
itPulsar = myioEnd();
for( auto& it : hist )
for( auto && it : hist )
{
for( auto && hit : it.hlst )
hit.ioit = myioEnd();
......@@ -331,7 +331,7 @@ void SharedMemory::checkHeartBeat()
bool wdtpingOK = true;
for( auto& it : hlist )
for( auto && it : hlist )
{
try
{
......@@ -378,7 +378,7 @@ void SharedMemory::checkHeartBeat()
// ------------------------------------------------------------------------------------------
bool SharedMemory::readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec )
{
for( auto& r : lstRSlot )
for( auto && r : lstRSlot )
{
try
{
......@@ -666,7 +666,7 @@ void SharedMemory::buildHistoryList( xmlNode* cnode )
// -----------------------------------------------------------------------------
void SharedMemory::checkHistoryFilter( UniXML::iterator& xit )
{
for( auto& it : hist )
for( auto && it : hist )
{
if( xit.getProp(it.filter).empty() )
continue;
......@@ -701,9 +701,9 @@ void SharedMemory::saveHistory()
if( hist.empty() )
return;
for( auto& it : hist )
for( auto && it : hist )
{
for( auto& hit : it.hlst )
for( auto && hit : it.hlst )
{
try
{
......@@ -743,7 +743,7 @@ void SharedMemory::updateHistory( std::shared_ptr<USensorInfo>& s_it, IOControll
<< " value=" << value
<< endl;
for( auto& it1 : i->second )
for( auto && it1 : i->second )
{
History::iterator it = it1;
......
......@@ -9,7 +9,7 @@
#include "Extensions.h"
#include "RTUExchange.h"
#include "MBSlave.h"
#include "MBTCPMultiSlave.h"
#include "MBTCPPersistentSlave.h"
#include "MBTCPMaster.h"
#include "SharedMemory.h"
//#include "UniExchange.h"
......@@ -215,7 +215,7 @@ int main( int argc, const char** argv )
dinfo << "(smemory-plus): add MBTCPMultiSlave(" << p.str() << ")" << endl;
auto mbs = MBTCPMultiSlave::init_mbslave(argc, argv, shm->getId(), shm, p.str());
auto mbs = MBTCPPersistentSlave::init_mbslave(argc, argv, shm->getId(), shm, p.str());
if( !mbs )
return 1;
......
......@@ -430,7 +430,7 @@ bool UNetExchange::checkExistUNetHost( const std::string& addr, ost::tpport_t po
{
ost::IPV4Address a1(addr.c_str());
for( auto& it : recvlist )
for( const auto& it : recvlist )
{
if( it.r1->getAddress() == a1.getAddress() && it.r1->getPort() == port )
return true;
......@@ -441,7 +441,7 @@ bool UNetExchange::checkExistUNetHost( const std::string& addr, ost::tpport_t po
// -----------------------------------------------------------------------------
void UNetExchange::startReceivers()
{
for( auto& it : recvlist )
for( const auto& it : recvlist )
{
if( it.r1 )
it.r1->start();
......@@ -701,7 +701,7 @@ void UNetExchange::sigterm( int signo )
unetinfo << myname << ": ********* SIGTERM(" << signo << ") ********" << endl;
activated = false;
for( auto& it : recvlist )
for( const auto& it : recvlist )
{
try
{
......@@ -745,7 +745,7 @@ void UNetExchange::initIterators()
if( sender2 )
sender2->initIterators();
for( auto& it : recvlist )
for( auto && it : recvlist )
it.initIterators(shm);
}
// -----------------------------------------------------------------------------
......@@ -814,7 +814,7 @@ std::shared_ptr<UNetExchange> UNetExchange::init_unetexchange( int argc, const c
// -----------------------------------------------------------------------------
void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceiver::Event ev )
{
for( auto& it : recvlist )
for( auto && it : recvlist )
{
if( it.r1 == r )
{
......
......@@ -285,8 +285,8 @@ void UNetReceiver::real_update()
if( sub >= maxDifferens )
{
// считаем сколько пакетов потеряли..
if( p.num > pnum )
// считаем сколько пакетов потеряли.. (pnum=0 - означает что мы только что запустились...)
if( pnum != 0 && p.num > pnum )
{
lostPackets += sub;
unetwarn << myname << "(update): sub=" << sub << " > maxDifferenst(" << maxDifferens << ")! lost " << sub << " packets " << endl;
......
......@@ -550,14 +550,28 @@ bool IOBase::initItem( IOBase* b, UniXML::iterator& it, const std::shared_ptr<SM
b->breaklim = initIntProp(it, "breaklim", prefix, init_prefix_only);
b->rawdata = initIntProp(it, "rawdata", prefix, init_prefix_only);
long msec = initIntProp(it, "debouncedelay", prefix, init_prefix_only, UniSetTimer::WaitUpTime);
b->ptDebounce.setTiming(msec);
long d_msec = initIntProp(it, "debouncedelay", prefix, init_prefix_only, UniSetTimer::WaitUpTime);
b->ptDebounce.setTiming(d_msec);
msec = initIntProp(it, "ondelay", prefix, init_prefix_only, UniSetTimer::WaitUpTime);
b->ptOnDelay.setTiming(msec);
long d_on_msec = initIntProp(it, "ondelay", prefix, init_prefix_only, UniSetTimer::WaitUpTime);
b->ptOnDelay.setTiming(d_on_msec);
long d_off_msec = initIntProp(it, "offdelay", prefix, init_prefix_only, UniSetTimer::WaitUpTime);
b->ptOffDelay.setTiming(d_off_msec);
if( dlog && d_msec != UniSetTimer::WaitUpTime
&& d_on_msec != UniSetTimer::WaitUpTime
&& d_off_msec != UniSetTimer::WaitUpTime )
{
dlog->warn() << myname <<"(IOBase::readItem): "
<< " 'debouncedelay' is used in conjunction with the 'ondelay' and 'offdelay'. Sure?"
<< " [ debouncedelay=" << d_msec
<< " ondelay=" << d_on_msec
<< " offdelay=" << d_off_msec
<< " ]" << endl;
}
msec = initIntProp(it, "offdelay", prefix, init_prefix_only, UniSetTimer::WaitUpTime);
b->ptOffDelay.setTiming(msec);
b->front = false;
std::string front_t( initProp(it, "iofront", prefix, init_prefix_only) );
......
......@@ -125,16 +125,16 @@ class DelayTimer
return check(prevState);
}
inline timeout_t getOnDelay()
inline timeout_t getOnDelay() const
{
return onDelay;
}
inline timeout_t getOffDelay()
inline timeout_t getOffDelay() const
{
return offDelay;
}
inline timeout_t getCurrent()
inline timeout_t getCurrent() const
{
return pt.getCurrent();
}
......
......@@ -2,6 +2,7 @@
#define LogReader_H_
// -------------------------------------------------------------------------
#include <string>
#include <memory>
#include <queue>
#include <vector>
#include <cc++/socket.h>
......@@ -73,7 +74,7 @@ class LogReader
timeout_t reconDelay;
private:
UTCPStream* tcp;
std::shared_ptr<UTCPStream> tcp;
std::string iaddr;
ost::tpport_t port;
bool cmdonly;
......
......@@ -113,7 +113,7 @@ class LogServer
DebugStream mylog;
std::shared_ptr< ThreadCreator<LogServer> > thr;
ost::TCPSocket* tcp;
std::shared_ptr<ost::TCPSocket> tcp;
std::shared_ptr<DebugStream> elog;
std::shared_ptr<NullLogSession> nullsess;
};
......
......@@ -70,6 +70,8 @@ class LogSession:
std::shared_ptr<LogAgregator> alog;
sigc::connection conn;
std::shared_ptr<LogSession> myptr;
// PassiveTimer ptSessionTimeout;
FinalSlot slFin;
std::atomic_bool cancelled;
......
......@@ -46,8 +46,8 @@ class UniSetTimer
virtual timeout_t setTiming( timeout_t msec ) = 0; /*!< установить таймер и запустить */
virtual void reset() = 0; /*!< перезапустить таймер */
virtual timeout_t getCurrent() = 0; /*!< получить текущее значение таймера */
virtual timeout_t getInterval() = 0; /*!< получить интервал, на который установлен таймер, в мс */
virtual timeout_t getCurrent() const = 0; /*!< получить текущее значение таймера */
virtual timeout_t getInterval() const = 0; /*!< получить интервал, на который установлен таймер, в мс */
timeout_t getLeft(timeout_t timeout) /*!< получить время, которое остается от timeout после прошествия времени getCurrent() */
{
timeout_t ct = getCurrent();
......@@ -104,8 +104,8 @@ class PassiveTimer:
virtual timeout_t setTiming( timeout_t msec ); /*!< установить таймер и запустить. timeMS = 0 вызовет немедленное срабатывание */
virtual void reset(); /*!< перезапустить таймер */
virtual timeout_t getCurrent(); /*!< получить текущее значение таймера, в мс */
virtual timeout_t getInterval() /*!< получить интервал, на который установлен таймер, в мс */
virtual timeout_t getCurrent() const override; /*!< получить текущее значение таймера, в мс */
virtual timeout_t getInterval() const override /*!< получить интервал, на который установлен таймер, в мс */
{
return (t_msec != UniSetTimer::WaitUpTime ? t_msec : 0);
}
......@@ -113,7 +113,7 @@ class PassiveTimer:
virtual void terminate(); /*!< прервать работу таймера */
protected:
timeout_t t_msec; /*!< интервал таймера, в милисекундах */
timeout_t t_msec = { 0 }; /*!< интервал таймера, в милисекундах */
std::chrono::high_resolution_clock::time_point t_start; /*!< время установки таймера (сброса) */
private:
......
......@@ -3,6 +3,7 @@
#define Pulse_H_
// --------------------------------------------------------------------------
#include <iostream>
#include <algorithm>
#include "PassiveTimer.h"
// --------------------------------------------------------------------------
/*! Класс реализующий формирование импульсов заданной длительности(t1) и заданных пауз между ними(t0).
......@@ -11,6 +12,8 @@
Формирование импульсов включается функцией run() либо функцией set(true).
Вызов reset() тоже включает формирование импульсов.
Выключается формирование вызовом set(false).
\warning Точность поддержания "импульсов" зависит от частоты вызова step() или out()
*/
class Pulse
{
......@@ -53,17 +56,13 @@ class Pulse
if( ostate && t1.checkTime() )
{
ostate = false;
// учитываем что step мог вызваться гораздо позже..
t0.setTiming( t0_msec - t1.getCurrent() % t1.getInterval() );
t0.setTiming(t0_msec);
}
if( !ostate && t0.checkTime() )
{
ostate = true;
// учитываем что step мог вызваться гораздо позже..
t1.setTiming(t1_msec - t0.getCurrent() % t0.getInterval() );
t1.setTiming(t1_msec);
}
return ostate;
......@@ -102,9 +101,19 @@ class Pulse
}
inline long getT1()
{
return t1_msec;
}
inline long getT0()
{
return t0_msec;
}
protected:
PassiveTimer t1; // таймер "1"
PassiveTimer t0; // таймер "0"
PassiveTimer tCorr; // корректирующий таймер
bool ostate;
bool isOn;
long t1_msec;
......
......@@ -16,7 +16,7 @@ class UTCPStream:
void create( const std::string& hname, int port, bool throwflag = false, timeout_t timer = 0 );
// set keepalive params
void setKeepAliveParams( timeout_t timeout_sec = 5, int conn_keepcnt = 1, int keepintvl=2 );
void setKeepAliveParams( timeout_t timeout_sec = 5, int conn_keepcnt = 1, int keepintvl = 2 );
protected:
......
......@@ -40,6 +40,8 @@ class ModbusTCPSession:
return caddr;
}
void setKeepAliveParams( timeout_t timeout_sec = 3, int conn_keepcnt = 2, int keepintvl = 2 );
protected:
virtual void run();
virtual void final();
......
......@@ -41,7 +41,10 @@ int ModbusTCPMaster::getNextData( unsigned char* buf, int len )
void ModbusTCPMaster::setChannelTimeout( timeout_t msec )
{
if( tcp )
{
tcp->setTimeout(msec);
tcp->setKeepAliveParams((msec > 1000 ? msec / 1000 : 1));
}
}
// -------------------------------------------------------------------------
mbErrCode ModbusTCPMaster::sendData( unsigned char* buf, int len )
......@@ -186,12 +189,16 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
ost::tpport_t port;
if( dlog->is_warn() )
{
const char* err = tcp->getErrorString();
dlog->warn() << "(ModbusTCPMaster::query): ret=" << (int)ret
<< " < rmh=" << (int)sizeof(rmh)
<< " errnum: " << tcp->getErrorNumber()
<< " perr: " << tcp->getPeer(&port)
<< " err: " << string(tcp->getErrorString())
<< " err: " << (err ? string(err) : "")
<< endl;
}
disconnect();
return erTimeOut; // return erHardwareError;
......@@ -306,7 +313,7 @@ bool ModbusTCPMaster::checkConnection( const std::string& ip, int port, int time
// Проверяем просто попыткой создать соединение..
UTCPStream t;
t.create(ip, port, true, timeout_msec);
t.setKeepAliveParams( (timeout_msec > 1000 ? timeout_msec/1000 : 1),1,1);
t.setKeepAliveParams( (timeout_msec > 1000 ? timeout_msec / 1000 : 1), 1, 1);
t.disconnect();
return true;
}
......@@ -333,7 +340,7 @@ void ModbusTCPMaster::reconnect()
tcp = make_shared<UTCPStream>();
tcp->create(iaddr, port, true, 500);
tcp->setTimeout(replyTimeOut_ms);
tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms/1000 : 1));
tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms / 1000 : 1));
}
catch( const std::exception& e )
{
......@@ -387,7 +394,7 @@ void ModbusTCPMaster::connect( ost::InetAddress addr, int _port )
tcp = make_shared<UTCPStream>();
tcp->create(iaddr, port, true, 500);
tcp->setTimeout(replyTimeOut_ms);
tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms/1000 : 1));
tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms / 1000 : 1));
}
catch( const std::exception& e )
{
......
......@@ -7,6 +7,8 @@
#include "modbus/ModbusTCPSession.h"
#include "modbus/ModbusTCPCore.h"
#include "UniSetTypes.h"
// glibc..
#include <netinet/tcp.h>
// -------------------------------------------------------------------------
using namespace std;
using namespace ModbusRTU;
......@@ -30,6 +32,14 @@ ModbusTCPSession::ModbusTCPSession( ost::TCPSocket& server, ModbusRTU::ModbusAdd
askCount(0)
{
setCRCNoCheckit(true);
timeout_t tout = timeout/1000;
if( tout <=0 )
tout = 3;
setKeepAlive(true);
setLinger(true);
setKeepAliveParams(tout);
}
// -------------------------------------------------------------------------
unsigned int ModbusTCPSession::getAskCount()
......@@ -38,6 +48,16 @@ unsigned int ModbusTCPSession::getAskCount()
return askCount;
}
// -------------------------------------------------------------------------
void ModbusTCPSession::setKeepAliveParams( timeout_t timeout_sec, int keepcnt, int keepintvl )
{
SOCKET fd = TCPSession::so;
int enable = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&enable, sizeof(enable));
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void*) &keepcnt, sizeof(keepcnt));
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void*) &keepintvl, sizeof (keepintvl));
setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (void*) &timeout_sec, sizeof (timeout_sec));
}
// -------------------------------------------------------------------------
void ModbusTCPSession::run()
{
if( cancelled )
......@@ -64,8 +84,16 @@ void ModbusTCPSession::run()
ModbusRTU::mbErrCode res = erTimeOut;
cancelled = false;
char pbuf[3];
while( !cancelled && isPending(Socket::pendingInput, timeout) )
{
ssize_t n = peek( pbuf, sizeof(pbuf) );
// кажется сервер закрыл канал
if( n == 0 )
break;
res = receive(addr, timeout);
if( res == erSessionClosed )
......
......@@ -60,7 +60,7 @@ void TCPCheck::check_thread()
ost::Thread::setException(ost::Thread::throwException);
UTCPStream t;
t.create(ip, port, true, tout_msec);
t.setKeepAliveParams( (tout_msec > 1000 ? tout_msec/1000 : 1) );
t.setKeepAliveParams( (tout_msec > 1000 ? tout_msec / 1000 : 1) );
setResult(true);
t.disconnect();
}
......
......@@ -27,8 +27,8 @@ void UTCPStream::setKeepAliveParams(timeout_t timeout_sec, int keepcnt, int keep
{
SOCKET fd = TCPStream::so;
int enable = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,(void*)&enable,sizeof(enable));
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void *) &keepcnt, sizeof(keepcnt));
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&enable, sizeof(enable));
setsockopt(fd, SOL_TCP, TCP_KEEPCNT, (void*) &keepcnt, sizeof(keepcnt));
setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, (void*) &keepintvl, sizeof (keepintvl));
setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, (void*) &timeout_sec, sizeof (timeout_sec));
}
......
......@@ -13,7 +13,6 @@ LogReader::LogReader():
inTimeout(10000),
outTimeout(6000),
reconDelay(5000),
tcp(0),
iaddr(""),
cmdonly(false),
readcount(0)
......@@ -50,9 +49,8 @@ void LogReader::connect( ost::InetAddress addr, ost::tpport_t _port, timeout_t m
{
if( tcp )
{
(*tcp) << endl;
(*tcp.get()) << endl;
disconnect();
delete tcp;
tcp = 0;
}
......@@ -71,7 +69,7 @@ void LogReader::connect( ost::InetAddress addr, ost::tpport_t _port, timeout_t m
try
{
tcp = new UTCPStream();
tcp = make_shared<UTCPStream>();
tcp->create(iaddr, port, true, 500);
tcp->setTimeout(msec);
tcp->setKeepAlive(true);
......@@ -85,7 +83,6 @@ void LogReader::connect( ost::InetAddress addr, ost::tpport_t _port, timeout_t m
rlog.crit() << s.str() << std::endl;
}
delete tcp;
tcp = 0;
}
catch( ... )
......@@ -110,7 +107,6 @@ void LogReader::disconnect()
rlog.info() << iaddr << "(LogReader): disconnect." << endl;
tcp->disconnect();
delete tcp;
tcp = 0;
}
// -------------------------------------------------------------------------
......@@ -200,6 +196,9 @@ void LogReader::sendCommand( const std::string& _addr, ost::tpport_t _port, std:
}
} // end for send all command
if( !isConnection() )
return;
// после команд.. выводим список текущий..
timeout_t reply_timeout = 2000; // TIMEOUT_INF;
......@@ -299,7 +298,7 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ
while( tcp->isPending(ost::Socket::pendingInput, inTimeout) )
{
int n = tcp->peek( buf, sizeof(buf) - 1 );
ssize_t n = tcp->peek( buf, sizeof(buf) - 1 );
if( n > 0 )
{
......@@ -308,6 +307,8 @@ void LogReader::readlogs( const std::string& _addr, ost::tpport_t _port, LogServ
log << buf;
}
else if( n == 0 && readcount <=0 )
break;
if( rcount > 0 && readcount > 0 )
rcount--;
......
......@@ -29,10 +29,11 @@ LogServer::~LogServer()
tcp->reject();
if( thr )
{
thr->stop();
delete tcp;
tcp = 0;
if( thr->isRunning() )
thr->join();
}
}
// -------------------------------------------------------------------------
LogServer::LogServer( std::shared_ptr<LogAgregator> log ):
......@@ -74,17 +75,7 @@ void LogServer::run( const std::string& addr, ost::tpport_t port, bool thread )
try
{
ost::InetAddress iaddr(addr.c_str());
tcp = new ost::TCPSocket(iaddr, port);
#if 0
if( !nullsess )
{
ostringstream err;
err << "(LOG SERVER): Exceeded the limit on the number of sessions = " << sessMaxCount << endl;
nullsess = make_shared<NullLogSession>(err.str());
}
#endif
tcp = make_shared<ost::TCPSocket>(iaddr, port);
}
catch( ost::Socket* socket )
{
......@@ -138,26 +129,28 @@ void LogServer::work()
ostringstream err;
err << "(LOG SERVER): Exceeded the limit on the number of sessions = " << sessMaxCount << endl;
nullsess = make_shared<NullLogSession>(err.str());
nullsess->detach(); // start();
//nullsess->detach();
nullsess->start();
}
else
nullsess->setMessage(err.str());
nullsess->add(*tcp);
nullsess->add(*(tcp.get())); // опасно передавать "сырой указатель", теряем контроль
continue;
}
}
if( cancelled ) break;
auto s = make_shared<LogSession>(*tcp, elog, sessTimeout, cmdTimeout, outTimeout);
auto s = make_shared<LogSession>( *(tcp.get()), elog, sessTimeout, cmdTimeout, outTimeout);
s->setSessionLogLevel(sessLogLevel);
{
uniset_rwmutex_wrlock l(mutSList);
slist.push_back(s);
}
s->connectFinalSession( sigc::mem_fun(this, &LogServer::sessionFinished) );
s->detach();
//s->detach();
s->start();
}
}
catch( ost::Socket* socket )
......@@ -175,6 +168,10 @@ void LogServer::work()
else
cerr << "client socket failed" << endl;
}
catch( const std::exception& ex )
{
cerr << "catch exception: " << ex.what() << endl;
}
}
{
......@@ -185,6 +182,12 @@ void LogServer::work()
if( nullsess )
nullsess->cancel();
}
for( const auto& i : slist )
{
if( i->isRunning() )
i->ost::Thread::join();
}
}
// -------------------------------------------------------------------------
void LogServer::sessionFinished( std::shared_ptr<LogSession> s )
......
......@@ -18,9 +18,9 @@ using namespace UniSetTypes;
// -------------------------------------------------------------------------
LogSession::~LogSession()
{
cancelled = true;
if( isRunning() )
{
cancelled = true;
ost::Thread::join();
disconnect();
}
......@@ -73,6 +73,10 @@ void LogSession::run()
if( cancelled )
return;
// удерживаем указатель на себя, пока работает поток..
myptr = shared_from_this();
cancelled = false;
{
ost::tpport_t p;
ost::InetAddress iaddr = getIPV4Peer(&p);
......@@ -95,7 +99,7 @@ void LogSession::run()
setKeepAlive(true);
// Команды могут посылаться только в начале сессии..
while( isPending(Socket::pendingInput, cmdTimeout) )
while( !cancelled && isPending(Socket::pendingInput, cmdTimeout) )
{
LogServerTypes::lsMessage msg;
......@@ -242,8 +246,6 @@ void LogSession::run()
#endif
cancelled = false;
while( !cancelled && isConnected() ) // !ptSessionTimeout.checkTime()
{
// проверка только ради проверки "целостности" соединения
......@@ -307,18 +309,22 @@ void LogSession::run()
disconnect();
cancelled = true;
if( slog.debugging(Debug::INFO) )
slog[Debug::INFO] << peername << "(run): thread stopping..." << endl;
myptr = 0;
}
// -------------------------------------------------------------------------
void LogSession::final()
{
tcp()->sync();
cancelled = true;
try
{
auto s = shared_from_this();
if( s )
slFin(s);
}
......@@ -344,8 +350,8 @@ NullLogSession::~NullLogSession()
{
cancelled = true;
if( isRunning() )
exit(); // terminate();
// if( isRunning() )
// exit(); // terminate();
}
// ---------------------------------------------------------------------
void NullLogSession::add( ost::TCPSocket& sock )
......
......@@ -126,8 +126,19 @@ UniSetTypes::IDList::IDList( std::vector<std::string>&& svec ):
UniSetTypes::IDList::IDList( std::vector<std::string>& svec ):
UniSetTypes::IDList::IDList()
{
auto conf = uniset_conf();
for( const auto& s : svec )
add( uni_atoi(s) );
{
ObjectId id;
if( is_digit(s) )
id = uni_atoi(s);
else
id = conf->getSensorID(s);
add(id);
}
}
// -------------------------------------------------------------------------
UniSetTypes::IDList::IDList():
......@@ -488,7 +499,7 @@ int UniSetTypes::uni_atoi( const char* str )
// чтобы корректно обрабатывать большие числа типа std::numeric_limits<unsigned int>::max()
// \warning есть сомнения, что на 64bit-тах это будет корректно работать..
int n = 0;
unsigned int n = 0;
if( strlen(str) > 2 )
{
......@@ -500,7 +511,7 @@ int UniSetTypes::uni_atoi( const char* str )
}
n = std::atoll(str); // универсальнее получать unsigned..чтобы не потерять "большие числа"..
return n;
return n; // а возвращаем int..
}
//--------------------------------------------------------------------------------------------
char* UniSetTypes::uni_strdup( const string& src )
......
......@@ -29,7 +29,7 @@
PassiveTimer::PassiveTimer( ):
PassiveTimer(WaitUpTime)
{
reset();
}
//------------------------------------------------------------------------------
......@@ -72,7 +72,7 @@ void PassiveTimer::reset(void)
}
//------------------------------------------------------------------------------
// получить текущее значение таймера
timeout_t PassiveTimer::getCurrent()
timeout_t PassiveTimer::getCurrent() const
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - t_start).count();
}
......
......@@ -105,7 +105,7 @@ namespace UniSetTypes
localNode(UniSetTypes::DefaultObjectId),
localNodeName(""),
fileConfName(""),
heartbeat_msec(10000)
heartbeat_msec(3000)
{
// ulog.crit()<< " configuration FAILED!!!!!!!!!!!!!!!!!" << endl;
// throw Exception();
......@@ -622,7 +622,7 @@ namespace UniSetTypes
heartbeat_msec = hit.getIntProp("msec");
if( heartbeat_msec <= 0 )
heartbeat_msec = 5000;
heartbeat_msec = 3000;
}
}
// -------------------------------------------------------------------------
......
......@@ -10,6 +10,10 @@ TEST_CASE("Pulse", "[Test for class 'Pulse' - impulse generator]" )
{
// Работа без задержки..(нулевые задержки)
Pulse p;
REQUIRE( p.getT1() == 0 );
REQUIRE( p.getT0() == 0 );
CHECK_FALSE( p.out() );
p.step();
......@@ -51,5 +55,18 @@ TEST_CASE("Pulse", "[Test for class 'Pulse' - impulse generator]" )
CHECK( p.step() );
msleep(110);
CHECK_FALSE( p.step() );
// проверка того, что при познем вызове step
// тоже всё будет хорошо..
p.reset();
CHECK( p.step() );
msleep(110);
CHECK_FALSE( p.step() );
msleep(2050);
CHECK( p.step() );
msleep(110);
CHECK_FALSE( p.step() );
msleep(70);
CHECK( p.step() );
}
}
......@@ -41,7 +41,7 @@ extensions/include/MBExchange.h
extensions/include/MBSlave.h
extensions/include/MBTCPMaster.h
extensions/include/MBTCPMultiMaster.h
extensions/include/MBTCPMultiSlave.h
extensions/include/MBTCPPersistentSlave.h
extensions/include/MTR.h
extensions/include/PassiveLProcessor.h
extensions/include/PID.h
......@@ -144,9 +144,9 @@ extensions/ModbusSlave/Makefile.am
extensions/ModbusSlave/MBSlave.cc
extensions/ModbusSlave/mbslave.cc
extensions/ModbusSlave/MBSlave.h
extensions/ModbusSlave/mbtcp-multislave.cc
extensions/ModbusSlave/MBTCPMultiSlave.cc
extensions/ModbusSlave/MBTCPMultiSlave.h
extensions/ModbusSlave/mbtcp-persistentslave.cc
extensions/ModbusSlave/MBTCPPersistentSlave.cc
extensions/ModbusSlave/MBTCPPersistentSlave.h
extensions/ModbusSlave/test.xml
extensions/RRDServer/libUniSet2RRDServer.pc.in
extensions/RRDServer/main.cc
......
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