Commit 36ba9983 authored by Aleksey Vinogradov's avatar Aleksey Vinogradov

Merge branch 'etersoft'

parents d7818975 ccbdc8a8
......@@ -128,172 +128,170 @@ int main(int argc, char** argv)
int optindex = 0;
char opt = 0;
while( (opt = getopt_long(argc, argv, "hc:beomsfur:l:i:x:g:w:y:p:",longopts,&optindex)) != -1 )
{
switch (opt) //разбираем параметры
while( (opt = getopt_long(argc, argv, "hc:beomsfur:l:i:x:g:w:y:p:",longopts,&optindex)) != -1 )
{
case 'h': //--help
usage();
return 0;
case 'c': //--confile
conffile = optarg;
break;
case 'o': //--omap
switch (opt) //разбираем параметры
{
uniset_init(argc,argv,conffile);
return omap();
}
break;
case 'h': //--help
usage();
return 0;
case 'b': //--create
{
uniset_init(argc,argv,conffile);
createSections(conf);
}
return 0;
case 'c': //--confile
conffile = optarg;
break;
case 'm': //--msgmap
{
uniset_init(argc,argv,conffile);
return msgmap();
}
break;
case 'x': //--setValue
{
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return setValue(optarg,ui);
}
break;
case 'o': //--omap
{
uniset_init(argc,argv,conffile);
return omap();
}
break;
case 'g': //--getValue
{
// cout<<"(main):received option --getValue='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return getValue(optarg,ui);
}
break;
case 'b': //--create
{
uniset_init(argc,argv,conffile);
createSections(conf);
}
return 0;
case 'm': //--msgmap
{
uniset_init(argc,argv,conffile);
return msgmap();
}
break;
case 'x': //--setValue
{
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return setValue(optarg,ui);
}
break;
case 'w': //--getRawValue
{
// cout<<"(main):received option --getRawValue='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return getRawValue(optarg,ui);
}
break;
case 'g': //--getValue
{
// cout<<"(main):received option --getValue='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return getValue(optarg,ui);
}
break;
case 'p': //--oinfo
{
// cout<<"(main):received option --oinfo='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return oinfo(optarg,ui);
}
break;
case 'w': //--getRawValue
{
// cout<<"(main):received option --getRawValue='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return getRawValue(optarg,ui);
}
break;
case 'e': //--exist
{
// cout<<"(main):received option --exist"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
Command cmd=Exist;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
// cout<<"(exist): done"<<endl;
}
return 0;
case 'p': //--oinfo
{
// cout<<"(main):received option --oinfo='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return oinfo(optarg,ui);
}
break;
case 's': //--start
{
// cout<<"(main):received option --start"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
case 'e': //--exist
{
// cout<<"(main):received option --exist"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
Command cmd=StartUp;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
}
return 0;
Command cmd=Exist;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
// cout<<"(exist): done"<<endl;
}
return 0;
case 'r': //--configure
{
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return configure(optarg,ui);
}
break;
case 's': //--start
{
// cout<<"(main):received option --start"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
Command cmd=StartUp;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
}
return 0;
case 'f': //--finish
{
// cout<<"(main):received option --finish"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
Command cmd=Finish;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
cout<<"(finish): done"<<endl;
}
return 0;
case 'r': //--configure
{
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return configure(optarg,ui);
}
break;
case 'l': //--logrotate
{
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return logRotate(optarg, ui);
}
break;
case 'f': //--finish
{
// cout<<"(main):received option --finish"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
Command cmd=Finish;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
cout<<"(finish): done"<<endl;
}
return 0;
case 'y': //--getCalibrate
{
// cout<<"(main):received option --getCalibrate='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return getCalibrate(optarg, ui);
}
break;
case 'l': //--logrotate
{
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return logRotate(optarg, ui);
}
break;
case 'y': //--getCalibrate
{
// cout<<"(main):received option --getCalibrate='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
return getCalibrate(optarg, ui);
}
break;
case 'u': //--foldUp
{
// cout<<"(main):received option --foldUp"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
case 'u': //--foldUp
{
// cout<<"(main):received option --foldUp"<<endl;
uniset_init(argc,argv,conffile);
UniversalInterface ui(conf);
Command cmd=FoldUp;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
// cout<<"(foldUp): done"<<endl;
}
return 0;
case '?':
default:
{
short_usage();
Command cmd=FoldUp;
ObjectRepository* rep = new ObjectRepository(conf);
commandToAll(conf->getServicesSection(), rep, (Command)cmd);
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
delete rep;
// cout<<"(foldUp): done"<<endl;
}
return 0;
}
}
}
case '?':
default:
{
short_usage();
return 1;
}
}
}
return 0;
}
......@@ -320,6 +318,8 @@ int main(int argc, char** argv)
{
cerr << "неизвестное исключение" << endl;
}
return 1;
}
// ==============================================================================================
......@@ -507,11 +507,11 @@ int setValue( const string args, UniversalInterface &ui, Configuration* conf )
switch(t)
{
case UniversalIO::DigitalInput:
ui.saveState(it->si.id,(it->val?true:false),t,it->si.node);
ui.saveState(it->si.id,(it->val?true:false),t,it->si.node);
break;
case UniversalIO::DigitalOutput:
ui.setState(it->si.id,(it->val?true:false),it->si.node);
ui.setState(it->si.id,(it->val?true:false),it->si.node);
break;
case UniversalIO::AnalogInput:
......
#!/bin/sh
./uniset-start.sh -f "./uniset-admin --confile test.xml --`basename $0 .sh` $1 $2 $3 $4"
exit $?
......@@ -70,6 +70,8 @@ int main(int argc, char** argv)
act.addObject(static_cast<class UniSetObject*>(&is));
act.run(false);
}
return 0;
}
catch(Exception& ex)
{
......@@ -80,5 +82,5 @@ int main(int argc, char** argv)
cerr << "(InfoServer::main): catch ..." << endl;
}
return 0;
return 1;
}
......@@ -23,13 +23,14 @@ static struct option longopts[] = {
// { "writefile15", required_argument, 0, 'p' },
{ "filetransfer66", required_argument, 0, 'u' },
{ "timeout", required_argument, 0, 't' },
{ "autodetect-slave", no_argument, 0, 'l' },
{ "autodetect-slave", no_argument, 0, 'q' },
{ "autodetect-speed", required_argument, 0, 'n' },
{ "device", required_argument, 0, 'd' },
{ "verbose", no_argument, 0, 'v' },
{ "myaddr", required_argument, 0, 'a' },
{ "speed", required_argument, 0, 's' },
{ "use485F", no_argument, 0, 'y' },
{ "num-cycles", required_argument, 0, 'q' },
{ NULL, 0, 0, 0 }
};
// --------------------------------------------------------------------------
......@@ -61,6 +62,7 @@ static void print_help()
printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n");
printf("[-s|--speed] speed - 9600,14400,19200,38400,57600,115200. Default: 38400.\n");
printf("[-t|--timeout] msec - Timeout. Default: 2000.\n");
printf("[-l|--num-cycles] num - Number of cycles of exchange. Default: -1 - infinitely.\n");
printf("[-v|--verbose] - Print all messages to stdout\n");
}
// --------------------------------------------------------------------------
......@@ -105,10 +107,11 @@ int main( int argc, char **argv )
DebugStream dlog;
string tofile("");
int use485 = 0;
int ncycles = -1;
try
{
while( (opt = getopt_long(argc, argv, "hva:w:z:m:r:x:c:b:d:s:t:ln:u:y",longopts,&optindex)) != -1 )
while( (opt = getopt_long(argc, argv, "hva:w:z:m:r:x:c:b:d:s:t:qn:u:yl:",longopts,&optindex)) != -1 )
{
switch (opt)
{
......@@ -255,7 +258,7 @@ int main( int argc, char **argv )
verb = 1;
break;
case 'l':
case 'q':
{
if( cmd == cmdNOP )
cmd = cmdDetectSlave;
......@@ -296,6 +299,10 @@ int main( int argc, char **argv )
fn = (ModbusRTU::SlaveFunctionCode)UniSetTypes::uni_atoi(argv[optind+1]);
}
break;
case 'l':
ncycles = uni_atoi(optarg);
break;
case '?':
default:
......@@ -321,7 +328,11 @@ int main( int argc, char **argv )
mb.setSpeed(speed);
mb.setLog(dlog);
while(1)
int nc = 1;
if( ncycles > 0 )
nc = ncycles;
while( nc )
{
try
{
......@@ -578,7 +589,15 @@ int main( int argc, char **argv )
throw ex;
cout << "timeout..." << endl;
}
}
if( ncycles > 0 )
{
nc--;
if( nc <=0 )
break;
}
msleep(200);
}
}
......
......@@ -113,9 +113,9 @@ int main( int argc, char **argv )
{
cerr << "(mbtcpserver): " << ex << endl;
}
catch( ost::SockException& e )
catch( std::exception& e )
{
cerr << e.getString() << ": " << e.getSystemErrorString() << endl;
cerr << "(mbtcpserver): " << e.what() << endl;
}
catch(...)
{
......
......@@ -23,6 +23,7 @@ static struct option longopts[] = {
{ "myaddr", required_argument, 0, 'a' },
{ "port", required_argument, 0, 'p' },
{ "persistent-connection", no_argument, 0, 'o' },
{ "num-cycles", required_argument, 0, 'l' },
{ NULL, 0, 0, 0 }
};
// --------------------------------------------------------------------------
......@@ -42,6 +43,7 @@ static void print_help()
printf("[-p|--port] port - Modbus server port. Default: 502.\n");
printf("[-t|--timeout] msec - Timeout. Default: 2000.\n");
printf("[-o|--persistent-connection] - Use persistent-connection.\n");
printf("[-l|--num-cycles] num - Number of cycles of exchange. Default: -1 - infinitely.\n");
printf("[-v|--verbose] - Print all messages to stdout\n");
}
// --------------------------------------------------------------------------
......@@ -77,10 +79,11 @@ int main( int argc, char **argv )
ModbusRTU::ModbusAddr slaveaddr = 0x00;
int tout = 2000;
DebugStream dlog;
int ncycles = -1;
try
{
while( (opt = getopt_long(argc, argv, "hva:w:z:r:x:c:b:d:s:t:p:i:o",longopts,&optindex)) != -1 )
while( (opt = getopt_long(argc, argv, "hva:w:z:r:x:c:b:d:s:t:p:i:ol:",longopts,&optindex)) != -1 )
{
switch (opt)
{
......@@ -182,6 +185,10 @@ int main( int argc, char **argv )
persist = true;
break;
case 'l':
ncycles = uni_atoi(optarg);
break;
case '?':
default:
printf("? argumnet\n");
......@@ -216,7 +223,11 @@ int main( int argc, char **argv )
if( count > ModbusRTU::MAXDATALEN && verb )
cout << "Too long packet! Max count=" << ModbusRTU::MAXDATALEN << " (ignore...)" << endl;
while(1)
int nc = 1;
if( ncycles > 0 )
nc = ncycles;
while( nc )
{
try
{
......@@ -406,7 +417,15 @@ int main( int argc, char **argv )
cout << "timeout..." << endl;
}
if( ncycles > 0 )
{
nc--;
if( nc <=0 )
break;
}
msleep(200);
} // end of while
mb.disconnect();
......@@ -423,9 +442,9 @@ int main( int argc, char **argv )
{
cerr << "(mbtester): " << ex << endl;
}
catch( ost::SockException& e )
catch( std::exception& e )
{
cerr << e.getString() << ": " << e.getSystemErrorString() << endl;
cerr << "(mbtester): " << e.what() << endl;
}
catch(...)
{
......
......@@ -2,16 +2,10 @@
# This file is part of the UniSet library #
############################################################################
UTILS = scripts Admin NullController SViewer-text \
SUBDIRS = scripts Admin NullController SViewer-text \
InfoServer SMonit MBTester codegen SImitator
#MapSourceParser ClassGen
if DISABLE_MYSQL
SUBDIRS = ${UTILS}
else
SUBDIRS = ${UTILS} DBServer-MySQL
endif
include $(top_builddir)/conf/common.mk
......
......@@ -77,6 +77,7 @@ int main(int argc, char** argv)
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(&nc));
act.run(false);
return 0;
}
catch(Exception& ex)
{
......@@ -87,5 +88,5 @@ int main(int argc, char** argv)
cerr << "(nullController::main): catch ..." << endl;
}
return 0;
return 1;
}
......@@ -40,6 +40,7 @@ int main( int argc, const char **argv )
SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() );
act.run(false);
return 0;
}
catch( Exception& ex )
{
......@@ -50,6 +51,6 @@ int main( int argc, const char **argv )
cout << "(main): Неизвестное исключение!!!!"<< endl;
}
return 0;
return 1;
}
// ------------------------------------------------------------------------------------------
......@@ -46,6 +46,8 @@ int main(int argc, const char **argv)
}
else
sv.view();
return 0;
}
catch(Exception& ex )
{
......@@ -56,5 +58,5 @@ int main(int argc, const char **argv)
cerr << "(main): Неизвестное исключение!!!!"<< endl;
}
return 0;
return 1;
}
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<!-- Генерирование cc-файла -->
<xsl:variable name="CLASSNAME">
......
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<!-- Генерирование cc-файла -->
<xsl:variable name="CLASSNAME">
......
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<xsl:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template>
......@@ -387,7 +387,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::setMsg( UniSetTypes::ObjectId _code
</xsl:when>
<xsl:when test="normalize-space(@iotype)='DO'">
<xsl:if test="normalize-space($onlymsg)=''">
if( prev_<xsl:call-template name="setprefix"/><xsl:value-of select="@name"/> != <xsl:call-template name="setprefix"/><xsl:value-of select="@name"/>, Message::Medium)
if( prev_<xsl:call-template name="setprefix"/><xsl:value-of select="@name"/> != <xsl:call-template name="setprefix"/><xsl:value-of select="@name"/> )
</xsl:if>
{
if( <xsl:value-of select="@name"/> != DefaultObjectId )
......
......@@ -3,7 +3,7 @@
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<xsl:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template>
......
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<xsl:template name="settype">
<xsl:param name="iotype"/>
......
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<xsl:variable name="CLASSNAME">
<xsl:call-template name="settings-alone"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template>
......
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<xsl:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template>
......
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<xsl:variable name="CLASSNAME">
<xsl:call-template name="settings-alone"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template>
......
<?xml version='1.0' encoding="koi8-r" ?>
<?xml version='1.0' encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/>
<xsl:output method="text" indent="yes" encoding="koi8-r"/>
<xsl:output method="text" indent="yes" encoding="utf-8"/>
<xsl:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template>
......
......@@ -17,7 +17,7 @@ print_usage()
{
[ "$1" = 0 ] || exec >&2
cat <<EOF
Usage: ${0##*/} [options] programm
Usage: ${0##*/} [options] programm [arguments]
Valid options are:
-h, --help display help screen
......@@ -33,6 +33,9 @@ EOF
[ -n "$1" ] && exit "$1" || exit
}
[ -z "$1" ] && print_usage 1
#parse command line options
case "$1" in
-h|--help) print_usage 0;;
......@@ -47,20 +50,30 @@ shift
if [ -n "$DBG" ]
then
COMLINE="$* --uniset-port $OMNIPORT"
COMLINE="$* --uniset-port $OMNIPORT"
start_line=
[ "$DBG" == "mem" ] && start_line="valgrind --tool=memcheck --leak-check=full --trace-children=yes --log-file=valgrind.log $COMLINE"
[ "$DBG" == "call" ] && start_line="valgrind --tool=callgrind --trace-children=yes --log-file=valgrind.log $COMLINE"
[ "$DBG" == "cache" ] && start_line="valgrind --tool=cachegrind --trace-children=yes --log-file=valgrind.log $COMLINE"
[ "$DBG" == "hel" ] && start_line="valgrind --tool=helgrind --trace-children=yes --log-file=valgrind.log $COMLINE"
PROG=`basename $1`
if [ "$DBG" == "gdb" ]; then
start_line="gdb --args $COMLINE"
if [ -a "./.libs/lt-$PROG" ]; then
PROG="./.libs/lt-$PROG"
else
if [ -a "./.libs/$PROG" ]; then
PROG="./.libs/$PROG"
fi
fi
shift
start_line="gdb --args $PROG $* --uniset-port $OMNIPORT"
fi
echo Running "$start_line"
$start_line
exit 0
exit $?
fi
if [ -n "$FG" ]
......@@ -69,20 +82,19 @@ then
if [ -z "$COMLINE" ]
then
echo "Не указана команда для запуска"
exit 0
exit 1
fi
COMLINE="$COMLINE --uniset-port $OMNIPORT"
echo Запускаем "$COMLINE"
$COMLINE
echo Выходим
exit 1
exit $?
fi
if [ -z "$*" ]
then
echo "Не указана команда для запуска"
exit 0
exit 1
fi
checkPID=$(echo "$1" | grep pidfile=)
......
......@@ -3,7 +3,7 @@
Name: libuniset
Version: 1.0
Release: alt14
Release: alt31
Summary: UniSet - library for building distributed industrial control systems
License: GPL
Group: Development/C++
......@@ -43,6 +43,16 @@ Obsoletes: %oname-mysql-dbserver
%description mysql-dbserver
MySQL dbserver for %name
%package mysql-devel
Group: Development/Databases
Summary: Libraries needed to develop for uniset MySQL
Requires: %name = %version-%release
Provides: %oname-mysql-devel
Obsoletes: %oname-mysql-devel
%description mysql-devel
Libraries needed to develop for uniset MySQL
%package utils
Summary: UniSet utilities
Group: Development/Tools
......@@ -54,7 +64,7 @@ Obsoletes: %oname-utils
UniSet utilities
%package doc
Group: Development/C
Group: Development/C++
Summary: Documentations for developing with UniSet
Requires: lib%name = %version-%release
......@@ -62,7 +72,7 @@ Requires: lib%name = %version-%release
Documentations for developing with UniSet
%package extensions
Group: Development/Databases
Group: Development/C++
Summary: libUniSet extensions
Requires: %name = %version-%release
Provides: %oname-extentions
......@@ -74,7 +84,7 @@ Obsoletes: %name-extentions
Extensions for libuniset
%package extensions-devel
Group: Development/Databases
Group: Development/C++
Summary: Libraries needed to develop for uniset extensions
Requires: %name-extensions = %version-%release
Provides: %name-extentions-devel
......@@ -135,6 +145,9 @@ rm -f %buildroot%_libdir/*.la
%_bindir/%oname-mysql-*dbserver
%_libdir/*-mysql.so*
%files mysql-devel
%_pkgconfigdir/libUniSetMySQL.pc
%if_enabled doc
%files doc
%_docdir/%name
......@@ -186,11 +199,69 @@ rm -f %buildroot%_libdir/*.la
%_pkgconfigdir/libUniSetShared*.pc
%_pkgconfigdir/libUniSetNetwork*.pc
%_pkgconfigdir/libUniSetUNet*.pc
#%_pkgconfigdir/libUniSetSMDBServer.pc
#%_pkgconfigdir/libUniSet*.pc
%exclude %_pkgconfigdir/libUniSet.pc
%changelog
* Fri May 13 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt31
- move DBServer-MySQL to extensions directory
- add pc-file for libUniSet-mysql
- create new devel package - "libuniset-mysql-devel"
- minor fixes
* Wed May 11 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt30
- add new function to UniversalInterface
* Sat May 07 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt29
- (unet2): new protocol implementation
* Thu May 05 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt28
- add setup function for ModbusTCPMaster and ModbusTCPServer
* Wed May 04 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt27
- fixed bug in ModbusTCPMaster and ModbusTCPServer
* Wed May 04 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt26
- minor fixes
* Wed May 04 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt25
- (unet2): minor fixes
* Sun May 01 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt24
- build for new uniset-unet2 version
* Sun May 01 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt23
- (uniset-unet2): fixed bug (SEGFAULT with a large number of items)
* Wed Apr 20 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt22
- (uniset-unet2-tester): fixed minor bugs
* Wed Apr 20 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt21
- (uniset-unet2-tester): add new parameter
-l | --check-lost - Check the lost packets.
* Wed Apr 20 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt20
- (uniset-unet2-tester): rename command line parameters
* Tue Apr 19 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt19
- a little cleaning
* Tue Apr 19 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt18
- add unet2-tester
* Tue Mar 29 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt17
- set encoding="utf-8" for codegen templates
* Tue Mar 29 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt16
- fixed minor bug in codegen
* Sat Mar 26 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt15
- fixed return value in some utilities
* Thu Mar 24 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt14
- fixed bug in MBSlave
......
......@@ -81,16 +81,16 @@
priority - приоритет сообщения об изменении данного датчика
textname - текстовое имя датчика
-->
<nodes port="2809">
<item infserver="InfoServer" ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="1" unet_port="3000" unet_ip="192.168.56.255">
<nodes port="2809" unet_broadcast_ip="192.168.1.255">
<item infserver="InfoServer" ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="0" unet_port="2048">
<iocards>
<item card="1" name="DI32"/>
<item card="2" name="DO32"/>
<item baddr="0x110" card="3" dev="/dev/comedi1" name="UNIO48" subdev1="TBI24_0" subdev2="TBI16_8"/>
</iocards>
</item>
<item ip="192.168.56.10" name="Node1" textname="Node1" unet_port="3001" unet_ip="192.168.56.255"/>
<item ip="192.168.56.11" name="Node2" textname="Node2" unet_port="3002" unet_ip="192.168.56.255"/>
<item ip="192.168.56.10" name="Node1" textname="Node1" unet_port="3001" unet_ip="192.168.56.255" unet_ignore="1"/>
<item ip="192.168.56.11" name="Node2" textname="Node2" unet_port="3002" unet_ip="192.168.56.255" unet_ignore="1"/>
</nodes>
<!-- ************************ Датчики ********************** -->
<sensors name="Sensors">
......
......@@ -3,7 +3,7 @@
# See doc: http://www.gnu.org/software/hello/manual/autoconf/Generic-Programs.html
# AC_PREREQ(2.59)
AC_INIT([uniset], [1.1.0], pv@etersoft.ru)
AC_INIT([uniset], [1.2.0], pv@etersoft.ru)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME,AC_PACKAGE_VERSION)
# AC_CONFIG_MACRO_DIR([m4])
......@@ -30,7 +30,7 @@ AC_ENABLE_SHARED(yes)
AC_ENABLE_STATIC(no)
AM_PROG_LIBTOOL
LIBVER=1:1:0
LIBVER=1:2:0
AC_SUBST(LIBVER)
# Checks for libraries.
......@@ -167,7 +167,6 @@ AC_CONFIG_FILES([Makefile
Utilities/SMonit/Makefile
Utilities/InfoServer/Makefile
Utilities/MBTester/Makefile
Utilities/DBServer-MySQL/Makefile
Utilities/SImitator/Makefile
Utilities/codegen/Makefile
Utilities/codegen/uniset-codegen
......@@ -176,14 +175,12 @@ AC_CONFIG_FILES([Makefile
extensions/libUniSetExtensions.pc
extensions/lib/Makefile
extensions/include/Makefile
extensions/DBServer-MySQL/Makefile
extensions/DBServer-MySQL/libUniSetMySQL.pc
extensions/IOControl/Makefile
extensions/IOControl/libUniSetIOControl.pc
extensions/RTUExchange/Makefile
extensions/RTUExchange/libUniSetRTU.pc
extensions/UDPExchange/Makefile
extensions/UDPExchange/libUniSetUDP.pc
extensions/UNet2/Makefile
extensions/UNet2/libUniSetUNet2.pc
extensions/ModbusSlave/Makefile
extensions/ModbusSlave/libUniSetMBSlave.pc
extensions/MBTCPMaster/Makefile
......@@ -193,6 +190,8 @@ AC_CONFIG_FILES([Makefile
extensions/SMViewer/Makefile
extensions/UniNetwork/Makefile
extensions/UniNetwork/libUniSetNetwork.pc
extensions/UNet2/Makefile
extensions/UNet2/libUniSetUNet2.pc
extensions/SharedMemory/Makefile
extensions/SharedMemory/libUniSetSharedMemory.pc
extensions/SharedMemoryPlus/Makefile])
......
if DISABLE_MYSQL
else
UMYSQL_VER=@LIBVER@
lib_LTLIBRARIES = libUniSet-mysql.la
......@@ -14,3 +18,8 @@ include $(top_builddir)/conf/setting.mk
# install
devel_include_HEADERS = *.h
devel_includedir = $(includedir)/@PACKAGE@/mysql
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libUniSetMySQL.pc
endif
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libUniSetMySQL
Description: Support library for libUniSetMySQL
Requires: libUniSet
Version: 1.0.0
Libs: -L${libdir} -lUniSet-mysql -lmysqlclient
Cflags: -I${includedir}/uniset -I${includedir}/mysql
......@@ -147,7 +147,7 @@ int main(int argc, char* argv[])
case '?':
default:
printf("? argument\n");
return 0;
return 1;
}
}
......@@ -419,7 +419,6 @@ void openXML()
}
uxml.close();
return;
}
catch( ... )
{
......
......@@ -65,6 +65,7 @@ int main(int argc, const char **argv)
act.run(true);
msleep(500);
ic->execute();
return 0;
}
catch(SystemError& err)
{
......@@ -79,5 +80,5 @@ int main(int argc, const char **argv)
dlog[Debug::CRIT] << "(iocontrol): catch(...)" << endl;
}
return 0;
return 1;
}
#ifndef LProcessor_H_
#define LProcessor_H_
// --------------------------------------------------------------------------
/*! \page pageLogicProcessor Логический процессор
\section sec_lpCommon Общее описание
Логический процессор представляет из себя процесс, который работает по принципу
PLC-контроллеров, выполняя бесконечный цикл:
\code
1. опрос входов
2. шаг алгоритма
3. выставление выходов
\endcode
При этом "логика" формируется из простых логических элементов:
-# \b "И" \b (AND)
-# \b "ИЛИ" \b (OR)
-# \b "Задержка" \b (Delay)
-# \b "Отрицание" \b (NOT)
\section sec_lpShema Конфигурирование
Конфигурирование процесса осуществляется при помощи xml-файла задающего
"схему соединения" элементов. Например
\code
<Schema>
<text-view>
----
1 --| |
2 --|TOR1|---| 1 -----
| | |----| |
---- 2 | |--|
|----|TAND3| |
---- | | | |
| | | ----- |
1 --|TOR2| | | 1 ---- -------
2 --| |--- | ---- ---| | | | out
| | | 1 | | 2 |TOR5|-----| Delay |----
---- |---|TOR4|-----| | | |
2 ----| | | | | |
---- ---- -------
</text-view>
<elements>
<item id="1" type="OR" inCount="2"/>
<item id="2" type="OR" inCount="2"/>
<item id="3" type="AND" inCount="2"/>
<item id="4" type="OR" inCount="2"/>
<item id="5" type="OR" inCount="2"/>
<item id="6" type="Delay" inCount="1" delayMS="3000"/>
</elements>
<connections>
<item type="ext" from="Input1_S" to="1" toInput="1" />
<item type="ext" from="Input2_S" to="1" toInput="2" />
<item type="ext" from="Input3_S" to="2" toInput="1" />
<item type="ext" from="Input4_S" to="2" toInput="2" />
<item type="ext" from="Input5_S" to="4" toInput="2" />
<item type="ext" from="Input6_S" to="5" toInput="1" />
<item type="int" from="1" to="3" toInput="1" />
<item type="int" from="2" to="3" toInput="2" />
<item type="int" from="3" to="4" toInput="1" />
<item type="int" from="4" to="5" toInput="2" />
<item type="int" from="5" to="6" toInput="1" />
<item type="out" from="6" to="Output1_C"/>
</connections>
</Schema>
\endcode
Блок \b <elements> содержит список элементов участвующих в "логике", каждому из
которых присвоен уникальный id, а также характеристики каждого элемента.
В секции \b <connections> задаютcя собственно соединения.
\par Тэги:
- \b type="ext" - Соединение связанное с внешним датчиком, задаваемым по имени.
- \b type="int" - Внутреннее соединение элементов между собой.
- \b type="out" - Замыкание на "внешний" датчик.
- \b from=".." - задаёт идентификатор элемента ("откуда"). Для type="ext", сюда пишется ID датчика.
- \b to=".." - задаёт идентификатор элемента("куда"), к которому происходит подключение.
- \b toInput=".." - В качестве значения указывается номер "входа" элемента из которого выходит "сигнал".
В текущей реализации в качестве датчиков разрешено использовать только типы DO или DI.
\note Следует иметь ввиду, что схема \b не \b обязательно должна быть \b "СВЯЗАННОЙ"
(все элементы связанны между собой). В файле может содержаться несколько схем внтури тэга \b <Schema>.
Логика исполняется в порядке следования в файле, сверху вниз (в порядке считывания из файла).
*/
// --------------------------------------------------------------------------
#include <map>
#include "UniSetTypes.h"
#include "UniversalInterface.h"
......
......@@ -10,6 +10,7 @@
#include "SMInterface.h"
#include "LProcessor.h"
// --------------------------------------------------------------------------
/*! Реализация LogicProccessor основанная на заказе датчиков */
class PassiveLProcessor:
public UniSetObject_LT,
protected LProcessor
......
......@@ -35,6 +35,7 @@ int main(int argc, const char **argv)
LProcessor plc;
plc.execute(schema);
return 0;
}
catch( LogicException& ex )
{
......@@ -49,6 +50,6 @@ int main(int argc, const char **argv)
cerr << " catch ... " << endl;
}
return 0;
return 1;
}
// -----------------------------------------------------------------------------
......@@ -81,7 +81,7 @@ int main(int argc, const char **argv)
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- IOControl START -------------------------\n\n";
act.run(false);
pause();
return 0;
}
catch( LogicException& ex )
{
......@@ -96,6 +96,6 @@ int main(int argc, const char **argv)
cerr << " catch ... " << endl;
}
return 0;
return 1;
}
// -----------------------------------------------------------------------------
......@@ -80,6 +80,9 @@ pollThread(0)
initPause = conf->getArgPInt("--" + prefix + "-initPause",it.getProp("initPause"), 3000);
sleepPause_usec = conf->getArgPInt("--" + prefix + "-sleepPause-usec",it.getProp("slepePause"), 100);
force = conf->getArgInt("--" + prefix + "-force",it.getProp("force"));
force_out = conf->getArgInt("--" + prefix + "-force-out",it.getProp("force_out"));
......@@ -182,6 +185,8 @@ void MBTCPMaster::initMB( bool reopen )
if( recv_timeout > 0 )
mb->setTimeout(recv_timeout);
mb->setSleepPause(sleepPause_usec);
dlog[Debug::INFO] << myname << "(init): ipaddr=" << iaddr << " port=" << port << endl;
if( dlog.debugging(Debug::LEVEL9) )
......
......@@ -420,6 +420,7 @@ class MBTCPMaster:
bool force_out; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID;
int polltime; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_usec;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
......
#include <sys/wait.h>
#include <sstream>
#include "MBTCPMaster.h"
#include "Configuration.h"
......@@ -69,6 +70,8 @@ int main( int argc, const char** argv )
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- MBTCP Exchange START -------------------------\n\n";
act.run(false);
while( waitpid(-1, 0, 0) > 0 );
return 0;
}
catch( Exception& ex )
{
......@@ -79,5 +82,6 @@ int main( int argc, const char** argv )
dlog[Debug::CRIT] << "(mbtcpmaster): catch ..." << std::endl;
}
return 0;
while( waitpid(-1, 0, 0) > 0 );
return 1;
}
#!/bin/sh
uniset-start.sh -f ./uniset-mbtcpmaster \
./uniset-start.sh -g ./uniset-mbtcpmaster \
--confile test.xml \
--mbtcp-name MBMaster1 \
--smemory-id SharedMemory \
......
......@@ -4,7 +4,7 @@
if HAVE_EXTENTIONS
SUBDIRS = lib include SharedMemory IOControl RTUExchange LogicProcessor \
ModbusSlave MBTCPMaster SMViewer UniNetwork UNet2
ModbusSlave MBTCPMaster SMViewer UniNetwork UNet2 DBServer-MySQL
#SMDBServer
#SharedMemoryPlus
#UDPExchange
......
// --------------------------------------------------------------------------
#include <sys/wait.h>
#include <sstream>
#include <string>
#include <cc++/socket.h>
......@@ -74,7 +75,8 @@ int main(int argc, const char **argv)
dlog[Debug::ANY] << "(main): -------------- MBSlave START -------------------------\n\n";
act.run(false);
while( waitpid(-1, 0, 0) > 0 );
return 0;
}
catch( SystemError& err )
{
......@@ -84,15 +86,16 @@ int main(int argc, const char **argv)
{
dlog[Debug::CRIT] << "(mbslave): " << ex << endl;
}
catch( ost::SockException& e )
catch( std::exception& e )
{
dlog[Debug::CRIT] << e.getString() << ": " << e.getSystemErrorString() << endl;
dlog[Debug::CRIT] << "(mbslave): " << e.what() << endl;
}
catch(...)
{
dlog[Debug::CRIT] << "(mbslave): catch(...)" << endl;
}
return 0;
while( waitpid(-1, 0, 0) > 0 );
return 1;
}
// --------------------------------------------------------------------------
......@@ -62,8 +62,9 @@ prefix(prefix_)
recv_timeout = conf->getArgPInt("--"+prefix+"-recv-timeout",it.getProp("recv_timeout"), 50);
int alltout = conf->getArgPInt("--"+prefix+"-all-timeout",it.getProp("all_timeout"), 2000);
ptAllNotRespond.setTiming(alltout);
sleepPause_usec = conf->getArgPInt("--" + prefix + "-sleepPause-usec",it.getProp("slepePause"), 100);
rs_pre_clean = conf->getArgInt("--"+prefix+"-pre-clean",it.getProp("pre_clean"));
noQueryOptimization = conf->getArgInt("--"+prefix+"-no-query-optimization",it.getProp("no_query_optimization"));
......@@ -184,6 +185,8 @@ void RTUExchange::initMB( bool reopen )
if( recv_timeout > 0 )
mb->setTimeout(recv_timeout);
mb->setSleepPause(sleepPause_usec);
dlog[Debug::INFO] << myname << "(init): dev=" << devname << " speed=" << ComPort::getSpeed(defSpeed) << endl;
}
......@@ -937,29 +940,6 @@ void RTUExchange::sigterm( int signo )
{
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false;
/*! \todo Нужно ли выставлять безопасное состояние. МОжно ведь не успеть совершить "обемен" */
// выставление безопасного состояния на выходы....
/*
RSMap::iterator it=rsmap.begin();
for( ; it!=rsmap.end(); ++it )
{
// if( it->stype!=UniversalIO::DigitalOutput && it->stype!=UniversalIO::AnalogOutput )
// continue;
if( it->safety == NoSafetyState )
continue;
try
{
}
catch( UniSetTypes::Exception& ex )
{
dlog[Debug::WARN] << myname << "(sigterm): " << ex << std::endl;
}
catch(...){}
}
*/
UniSetObject_LT::sigterm(signo);
}
// ------------------------------------------------------------------------------------------
......
......@@ -244,6 +244,7 @@ class RTUExchange:
bool force_out; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID;
int polltime; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_usec;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
......
......@@ -363,6 +363,7 @@ int main( int argc, char **argv )
return 1;
}
return 0;
}
catch( ModbusRTU::mbException& ex )
{
......@@ -381,7 +382,7 @@ int main( int argc, char **argv )
cerr << "(mtr-setup): catch(...)" << endl;
}
return 0;
return 1;
}
// --------------------------------------------------------------------------
char* checkArg( int i, int argc, char* argv[] )
......
......@@ -120,6 +120,7 @@ int main( int argc, const char **argv )
else
{
cout << " Unknown type: " << type << endl;
return 1;
}
return 0;
......
#include <sys/wait.h>
#include <sstream>
#include "ObjectsActivator.h"
#include "Extensions.h"
......@@ -68,8 +69,9 @@ int main( int argc, char** argv )
dlog[Debug::ANY] << "(main): -------------- RTU Exchange START -------------------------\n\n";
act.run(false);
// msleep(500);
// rs->execute();
while( waitpid(-1, 0, 0) > 0 );
return 0;
}
catch( Exception& ex )
{
......@@ -80,5 +82,6 @@ int main( int argc, char** argv )
dlog[Debug::CRIT] << "(rtuexchange): catch ..." << std::endl;
}
return 0;
while( waitpid(-1, 0, 0) > 0 );
return 1;
}
......@@ -108,6 +108,8 @@ int main( int argc, char **argv )
cout << "UNIO1 AI" << i << ": " << rtu.getFloat( RTUStorage::nJ1, i, UniversalIO::AnalogInput ) << endl;
for( int i=0; i<24; i++ )
cout << "UNIO1 DI" << i << ": " << rtu.getState( RTUStorage::nJ1, i, UniversalIO::DigitalInput ) << endl;
return 0;
}
catch( ModbusRTU::mbException& ex )
{
......@@ -126,6 +128,6 @@ int main( int argc, char **argv )
cerr << "(rtustate): catch(...)" << endl;
}
return 0;
return 1;
}
// --------------------------------------------------------------------------
......@@ -69,6 +69,7 @@ int main( int argc, const char** argv )
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- SMDBServer START -------------------------\n\n";
act.run(false);
return 0;
}
catch( Exception& ex )
{
......@@ -79,5 +80,5 @@ int main( int argc, const char** argv )
dlog[Debug::CRIT] << "(smdbserver): catch ..." << std::endl;
}
return 0;
return 1;
}
......@@ -36,6 +36,7 @@ int main( int argc, const char **argv )
SMViewer smv(shmID);
smv.run();
return 0;
}
catch( Exception& ex )
{
......@@ -46,6 +47,6 @@ int main( int argc, const char **argv )
cout << "Неизвестное исключение!!!!"<< endl;
}
return 0;
return 1;
}
// ------------------------------------------------------------------------------------------
......@@ -42,14 +42,18 @@ int main(int argc, const char **argv)
// pause(); // пауза, чтобы дочерние потоки успели завершить работу
return 0;
}
catch(SystemError& err)
catch( SystemError& err )
{
unideb[Debug::CRIT] << "(smemory): " << err << endl;
}
catch(Exception& ex)
catch( Exception& ex )
{
unideb[Debug::CRIT] << "(smemory): " << ex << endl;
}
catch( std::exception& e )
{
unideb[Debug::CRIT] << "(smemory): " << e.what() << endl;
}
catch(...)
{
unideb[Debug::CRIT] << "(smemory): catch(...)" << endl;
......
bin_PROGRAMS = @PACKAGE@-udpexchange @PACKAGE@-udpsender @PACKAGE@-udpreceiver
# не забывайте править версию в pc-файле
UUDP_VER=@LIBVER@
lib_LTLIBRARIES = libUniSetUDP.la
libUniSetUDP_la_LDFLAGS = -version-info $(UUDP_VER)
libUniSetUDP_la_LIBADD = $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
libUniSetUDP_la_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
libUniSetUDP_la_SOURCES = UDPPacket.cc UDPExchange.cc UDPSender.cc UDPNReceiver.cc UDPReceiver.cc
#UDPSender.cc
@PACKAGE@_udpexchange_SOURCES = udpexchange.cc
@PACKAGE@_udpexchange_LDADD = libUniSetUDP.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_udpexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_udpsender_SOURCES = udpsender.cc
@PACKAGE@_udpsender_LDADD = libUniSetUDP.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_udpsender_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_udpreceiver_SOURCES = udpreceiver.cc
@PACKAGE@_udpreceiver_LDADD = libUniSetUDP.la $(top_builddir)/lib/libUniSet.la \
$(top_builddir)/extensions/SharedMemory/libUniSetSharedMemory.la \
$(top_builddir)/extensions/lib/libUniSetExtensions.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_udpreceiver_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
# install
devel_include_HEADERS = *.h
devel_includedir = $(pkgincludedir)/extensions
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libUniSetUDP.pc
all-local:
ln -sf ../UDPExchange/$(devel_include_HEADERS) ../include
#ifndef UDPExchange_H_
#define UDPExchange_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
#include "UDPNReceiver.h"
// -----------------------------------------------------------------------------
class UDPExchange:
public UniSetObject_LT
{
public:
UDPExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
virtual ~UDPExchange();
/*! глобальная функция для инициализации объекта */
static UDPExchange* init_udpexchange( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
struct UItem
{
UItem():
val(0)
{}
IOController_i::SensorInfo si;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniSetTypes::uniset_spin_mutex val_lock;
UniSetUDP::UDPMessage::UDPDataList::iterator pack_it;
long val;
friend std::ostream& operator<<( std::ostream& os, UItem& p );
};
protected:
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void poll();
void recv();
void send();
void step();
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm );
void askSensors( UniversalIO::UIOCommand cmd );
void waitSMReady();
virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo );
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
void readConfiguration();
bool check_item( UniXML_iterator& it );
void buildReceiverList();
private:
UDPExchange();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
int polltime; /*!< переодичность обновления данных, [мсек] */
ost::UDPBroadcast* udp;
ost::IPV4Host host;
ost::tpport_t port;
std::string s_host;
UniSetTypes::uniset_mutex pollMutex;
Trigger trTimeout;
int recvTimeout;
int sendTimeout;
bool activated;
int activateTimeout;
UniSetUDP::UDPMessage mypack;
typedef std::vector<UItem> DMap;
DMap dlist;
int maxItem;
typedef std::list<UDPNReceiver*> ReceiverList;
ReceiverList rlist;
ThreadCreator<UDPExchange>* thr;
};
// -----------------------------------------------------------------------------
#endif // UDPExchange_H_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UDPNReceiver.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UDPNReceiver::UDPNReceiver( ost::tpport_t p, ost::IPV4Host h, UniSetTypes::ObjectId shmId, IONotifyController* ic ):
shm(0),
ui(conf),
activate(false),
udp(0),
host(h),
port(p),
recvTimeout(5000),
conn(false)
{
{
ostringstream s;
s << host << ":" << port;
myname = s.str();
}
shm = new SMInterface(shmId,&ui,DefaultObjectId,ic);
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UDPNReceiver): UDP set to " << host << ":" << port << endl;
try
{
udp = new ost::UDPDuplex(host,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString() << endl;
throw SystemError(s.str());
}
thr = new ThreadCreator<UDPNReceiver>(this, &UDPNReceiver::poll);
thr->start();
}
// -----------------------------------------------------------------------------
UDPNReceiver::~UDPNReceiver()
{
delete udp;
delete shm;
delete thr;
}
// -----------------------------------------------------------------------------
void UDPNReceiver::poll()
{
while( 1 )
{
if( !activate )
{
msleep(1000);
continue;
}
try
{
recv();
}
catch( ost::SockException& e )
{
cerr << e.getString() << ": " << e.getSystemErrorString() << endl;
}
catch( UniSetTypes::Exception& ex)
{
cerr << myname << "(step): " << ex << std::endl;
}
catch(...)
{
cerr << myname << "(step): catch ..." << std::endl;
}
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UDPNReceiver::recv()
{
cout << myname << ": recv....(timeout=" << recvTimeout << ")" << endl;
// UniSetUDP::UDPHeader h;
// receive
if( udp->isInputReady(recvTimeout) )
{
/*
size_t ret = udp->UDPReceive::receive(&h,sizeof(h));
if( ret<(size_t)sizeof(h) )
{
cerr << myname << "(receive): ret=" << ret << " sizeof=" << sizeof(h) << endl;
return;
}
cout << myname << "(receive): header: " << h << endl;
if( h.dcount <=0 )
{
cout << " data=0" << endl;
return;
}
*/
UniSetUDP::UDPData d;
// ignore echo...
#if 0
if( h.nodeID == conf->getLocalNode() && h.procID == getId() )
{
for( int i=0; i<h.dcount;i++ )
{
size_t ret = udp->UDPReceive::receive(&d,sizeof(d));
if( ret < (size_t)sizeof(d) )
return;
}
return;
}
#endif
for( int i=0; i<100;i++ )
{
size_t ret = udp->UDPReceive::receive(&d,sizeof(d));
if( ret<(size_t)sizeof(d) )
{
cerr << myname << "(receive data " << i << "): ret=" << ret << " sizeof=" << sizeof(d) << endl;
break;
}
cout << myname << "(receive data " << i << "): " << d << endl;
}
}
// else
// {
// cout << "no InputReady.." << endl;
// }
}
// -----------------------------------------------------------------------------
#ifndef UDPNReceiver_H_
#define UDPNReceiver_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "Mutex.h"
#include "Trigger.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
class UDPNReceiver
{
public:
UDPNReceiver( ost::tpport_t port, ost::IPV4Host host, UniSetTypes::ObjectId shmID, IONotifyController* ic=0 );
virtual ~UDPNReceiver();
inline int getPort(){ return port; }
inline bool isConnetcion(){ return conn; }
inline void start(){ activate = true; }
inline void stop(){ activate = false; }
inline void setReceiveTimeout( int t ){ recvTimeout = t; }
inline std::string getName(){ return myname; }
protected:
SMInterface* shm;
UniversalInterface ui;
void poll();
void recv();
std::string myname;
private:
UDPNReceiver();
bool activate;
ost::UDPDuplex* udp;
ost::IPV4Host host;
ost::tpport_t port;
int recvTimeout;
bool conn;
ThreadCreator<UDPNReceiver>* thr;
};
// -----------------------------------------------------------------------------
#endif // UDPNReceiver_H_
// -----------------------------------------------------------------------------
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetUDP;
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPHeader& p )
{
return os << "nodeID=" << p.nodeID
<< " procID=" << p.procID
<< " dcount=" << p.dcount;
}
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPData& p )
{
return os << "id=" << p.id << " val=" << p.val;
}
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPMessage& p )
{
return os;
}
// -----------------------------------------------------------------------------
UDPMessage::UDPMessage()
{
}
// -----------------------------------------------------------------------------
void UDPMessage::addData( const UniSetUDP::UDPData& dat )
{
dlist.push_back(dat);
}
// -----------------------------------------------------------------------------
void UDPMessage::addData( long id, long val)
{
UDPData d(id,val);
addData(d);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
#ifndef UDPPacket_H_
#define UDPPacket_H_
// -----------------------------------------------------------------------------
#include <list>
#include <ostream>
#include "UniSetTypes.h"
// -----------------------------------------------------------------------------
namespace UniSetUDP
{
struct UDPHeader
{
long nodeID;
long procID;
long dcount;
friend std::ostream& operator<<( std::ostream& os, UDPHeader& p );
}__attribute__((packed));
struct UDPData
{
UDPData():id(UniSetTypes::DefaultObjectId),val(0){}
UDPData(long id, long val):id(id),val(val){}
long id;
long val;
friend std::ostream& operator<<( std::ostream& os, UDPData& p );
}__attribute__((packed));
struct UDPMessage:
public UDPHeader
{
UDPMessage();
void addData( const UDPData& dat );
void addData( long id, long val );
inline int size(){ return dlist.size(); }
typedef std::list<UDPData> UDPDataList;
UDPDataList dlist;
friend std::ostream& operator<<( std::ostream& os, UDPMessage& p );
};
}
// -----------------------------------------------------------------------------
#endif // UDPPacket_H_
// -----------------------------------------------------------------------------
#ifndef UDPReceiver_H_
#define UDPReceiver_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
class UDPReceiver:
public UniSetObject_LT
{
public:
UDPReceiver( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
virtual ~UDPReceiver();
/*! глобальная функция для инициализации объекта */
static UDPReceiver* init_udpreceiver( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
protected:
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void poll();
void recv();
void step();
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm );
void askSensors( UniversalIO::UIOCommand cmd );
void waitSMReady();
virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo );
void initIterators();
private:
UDPReceiver();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
int polltime; /*!< переодичность обновления данных, [мсек] */
ost::UDPDuplex* udp;
ost::IPV4Host host;
ost::tpport_t port;
UniSetTypes::uniset_mutex pollMutex;
Trigger trTimeout;
int recvTimeout;
bool activated;
int activateTimeout;
ThreadCreator<UDPReceiver>* thr;
};
// -----------------------------------------------------------------------------
#endif // UDPReceiver_H_
// -----------------------------------------------------------------------------
#ifndef UDPSender_H_
#define UDPSender_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
class UDPSender:
public UniSetObject_LT
{
public:
UDPSender( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
virtual ~UDPSender();
/*! глобальная функция для инициализации объекта */
static UDPSender* init_udpsender( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
struct UItem
{
UItem():
val(0)
{}
IOController_i::SensorInfo si;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniSetTypes::uniset_spin_mutex val_lock;
UniSetUDP::UDPMessage::UDPDataList::iterator pack_it;
long val;
friend std::ostream& operator<<( std::ostream& os, UItem& p );
};
protected:
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void poll();
void recv();
void send();
void step();
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm );
void askSensors( UniversalIO::UIOCommand cmd );
void waitSMReady();
virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo );
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
void readConfiguration();
bool check_item( UniXML_iterator& it );
private:
UDPSender();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
int sendtime; /*!< переодичность посылки данных, [мсек] */
ost::UDPSocket* udp;
ost::IPV4Host host;
ost::tpport_t port;
UniSetTypes::uniset_mutex sendMutex;
Trigger trTimeout;
int sendTimeout;
bool activated;
int activateTimeout;
UniSetUDP::UDPMessage mypack;
typedef std::vector<UItem> DMap;
DMap dlist;
int maxItem;
ThreadCreator<UDPSender>* thr;
};
// -----------------------------------------------------------------------------
#endif // UDPSender_H_
// -----------------------------------------------------------------------------
#ifndef UNetExchange_H_
#define UNetExchange_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <queue>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UNetReceiver.h"
#include "UNetSender.h"
// -----------------------------------------------------------------------------
class UNetExchange:
public UniSetObject_LT
{
public:
UNetExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
virtual ~UNetExchange();
/*! глобальная функция для инициализации объекта */
static UNetExchange* init_unetexchange( int argc, char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
bool checkExistUNetHost( const std::string host, ost::tpport_t port );
protected:
xmlNode* cnode;
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void step();
virtual void processingMessage( UniSetTypes::VoidMessage *msg );
void sysCommand( UniSetTypes::SystemMessage *msg );
void sensorInfo( UniSetTypes::SensorMessage*sm );
void timerInfo( UniSetTypes::TimerMessage *tm );
void askSensors( UniversalIO::UIOCommand cmd );
void waitSMReady();
virtual bool activateObject();
// действия при завершении работы
virtual void sigterm( int signo );
void initIterators();
void startReceivers();
void initSender( const std::string host, const ost::tpport_t port, UniXML_iterator& it );
enum Timer
{
tmStep
};
private:
UNetExchange();
bool initPause;
UniSetTypes::uniset_mutex mutex_start;
PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat;
int maxHeartBeat;
IOController::AIOStateList::iterator aitHeartBeat;
UniSetTypes::ObjectId test_id;
int steptime; /*!< периодичность вызова step, [мсек] */
bool activated;
int activateTimeout;
typedef std::list<UNetReceiver*> ReceiverList;
ReceiverList recvlist;
bool no_sender; /*!< флаг отключения посылки сообщений */
UNetSender* sender;
};
// -----------------------------------------------------------------------------
#endif // UNetExchange_H_
// -----------------------------------------------------------------------------
#ifndef UNetReceiver_H_
#define UNetReceiver_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <queue>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
// -----------------------------------------------------------------------------
/* Основная идея: сделать проверку очерёдности пакетов, но при этом использовать UDP.
* ===============
* Собственно реализация сделана так:
* В данных передаётся номер пакета. На случай если несколько пакетов придут не в той последовательности
* что были посланы, сделана очередь с приоритетом. В качестве приориета используется номер пакета
* (чем меньше тем старше). При этом обработка ведётся только тех пакетов, которые идут "подряд",
* как только встречается "дырка" происходит ожидание её "заполения". Если в течение времени (lostTimeout)
* "дырка" не исчезает, увеличивается счётчик потерянных пакетов и обработка продолжается дальше..
* Всё это реализовано в функции UNetReceiver::real_update()
*
* КЭШ
* ===
* Для оптимизации работы с SM, т.к. в пакетах приходят только пары [id,value] сделан кэш итераторов.
* Кэш расчитан на то, что принимаемые пакеты всегда имеют одну и ту же длину и последовательность.
* Идея проста: сделан вектор размером с количество принимаемых данных. В векторе хранятся итераторы (и всё что необходимо).
* Порядокый номер данных в пакете является индексом в кэше.
* Для защиты от изменения поседовательности внутри пакета, в кэше хранится ID сохраняемого датчика, и если он не совпадёт с тем,
* ID который пришёл в пакете - элемент кэша обновляется.
* Если количество пришедших данных не совпадают с размером кэша.. кэш обновляется.
*
* Обработка сбоя или переполнения счётчика пакетов(перехода через максимум)
* =========================================================================
* Для защиты от сбоя счётика сделана следующая логика:
* Если номер очередного пришедшего пакета отличается от последнего обработанного на maxDifferens, то считается,
* что произошёл сбой счётчика и происходит ожидание пока функция update, не обработает основную очередь полностью.
* При этом принимаемые пакеты складываются во временную очередь qtmp. Как только основная очередь пустеет,
* в неё копируется всё накопленное во временной очереди..и опять идёт штатная обработка.
* Если во время "ожидания" опять происходит "разрыв" в номерах пакетов, то временная очередь чиститься
* и данные которые в ней были теряются! Аналог ограниченного буфера (у любых карт), когда новые данные
* затирают старые, если их не успели вынуть и обработать.
* \todo Сделать защиту от бесконечного ожидания "очистки" основной очереди.
*/
// -----------------------------------------------------------------------------
class UNetReceiver
{
public:
UNetReceiver( const std::string host, const ost::tpport_t port, SMInterface* smi );
~UNetReceiver();
void start();
void receive();
void update();
inline bool isRecvOK(){ return ptRecvTimeout.checkTime(); }
inline unsigned long getLostPacketsNum(){ return lostPackets; }
void setReceiveTimeout( timeout_t msec );
void setReceivePause( timeout_t msec );
void setUpdatePause( timeout_t msec );
void setLostTimeout( timeout_t msec );
void setMaxDifferens( unsigned long set );
void setMaxProcessingCount( int set );
inline ost::IPV4Address getAddress(){ return addr; }
inline ost::tpport_t getPort(){ return port; }
protected:
SMInterface* shm;
bool recv();
void step();
void real_update();
void initIterators();
private:
UNetReceiver();
int recvpause; /*!< пауза меджду приёмами пакетов, [мсек] */
int updatepause; /*!< переодичность обновления данных в SM, [мсек] */
ost::UDPReceive* udp;
ost::IPV4Address addr;
ost::tpport_t port;
std::string myname;
UniSetTypes::uniset_mutex pollMutex;
PassiveTimer ptRecvTimeout;
timeout_t recvTimeout;
timeout_t lostTimeout;
PassiveTimer ptLostTimeout;
unsigned long lostPackets; /*!< счётчик потерянных пакетов */
bool activated;
ThreadCreator<UNetReceiver>* r_thr; // receive thread
ThreadCreator<UNetReceiver>* u_thr; // update thread
// функция определения приоритетного сообщения для обработки
struct PacketCompare:
public std::binary_function<UniSetUDP::UDPMessage, UniSetUDP::UDPMessage, bool>
{
bool operator()(const UniSetUDP::UDPMessage& lhs,
const UniSetUDP::UDPMessage& rhs) const;
};
typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue;
PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */
UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очереlного сообщения */
UniSetTypes::uniset_mutex packMutex; /*!< mutex для работы с очередью */
unsigned long pnum; /*!< текущий номер обработанного сообщения, для проверки непрерывности последовательности пакетов */
/*! максимальная разница межд номерами пакетов, при которой считается, что счётчик пакетов
* прошёл через максимум или сбился...
*/
unsigned long maxDifferens;
PacketQueue qtmp; /*!< очередь на время обработки(очистки) основной очереди */
bool waitClean; /*!< флаг означающий, что ждём очистики очереди до конца */
unsigned long rnum; /*!< текущий номер принятого сообщения, для проверки "переполнения" или "сбоя" счётчика */
int maxProcessingCount; /*! максимальное число обрабатываемых за один раз сообщений */
struct ItemInfo
{
long id;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniversalIO::IOTypes iotype;
};
typedef std::vector<ItemInfo> ItemVec;
ItemVec icache; /*!< кэш итераторов */
bool cache_init_ok;
void initCache( UniSetUDP::UDPMessage& pack, bool force=false );
};
// -----------------------------------------------------------------------------
#endif // UNetReceiver_H_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UNetSender.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UNetSender::UNetSender( const std::string s_host, const ost::tpport_t port, SMInterface* smi,
const std::string s_f, const std::string s_val, SharedMemory* ic ):
s_field(s_f),
s_fvalue(s_val),
shm(smi),
s_host(s_host),
sendpause(150),
activated(false),
dlist(100),
maxItem(0),
packetnum(1),
s_thr(0)
{
{
ostringstream s;
s << "(" << s_host << ":" << port << ")";
myname = s.str();
}
// определяем фильтр
// s_field = conf->getArgParam("--udp-filter-field");
// s_fvalue = conf->getArgParam("--udp-filter-value");
dlog[Debug::INFO] << myname << "(init): read fileter-field='" << s_field
<< "' filter-value='" << s_fvalue << "'" << endl;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UNetSender): UDP set to " << s_host << ":" << port << endl;
try
{
addr = s_host.c_str();
udp = new ost::UDPBroadcast(addr,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString() << endl;
throw SystemError(s.str());
}
s_thr = new ThreadCreator<UNetSender>(this, &UNetSender::send);
// -------------------------------
if( shm->isLocalwork() )
{
readConfiguration();
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
}
else
ic->addReadItem( sigc::mem_fun(this,&UNetSender::readItem) );
// выставляем поля, которые не меняются
mypack.msg.header.nodeID = conf->getLocalNode();
mypack.msg.header.procID = shm->ID();
}
// -----------------------------------------------------------------------------
UNetSender::~UNetSender()
{
delete s_thr;
delete udp;
delete shm;
}
// -----------------------------------------------------------------------------
void UNetSender::update( UniSetTypes::ObjectId id, long value )
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
if( it->si.id == id )
{
uniset_spin_lock lock(it->val_lock);
it->val = value;
}
break;
}
}
// -----------------------------------------------------------------------------
void UNetSender::send()
{
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
/*
ost::IPV4Broadcast h = s_host.c_str();
try
{
udp->setPeer(h,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << myname << "(poll): " << s.str() << endl;
throw SystemError(s.str());
}
*/
while( activated )
{
try
{
real_send();
}
catch( ost::SockException& e )
{
cerr << e.getString() << ": " << e.getSystemErrorString() << endl;
}
catch( UniSetTypes::Exception& ex)
{
cerr << myname << "(send): " << ex << std::endl;
}
catch(...)
{
cerr << myname << "(send): catch ..." << std::endl;
}
msleep(sendpause);
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UNetSender::real_send()
{
mypack.msg.header.num = packetnum++;
if( packetnum > UniSetUDP::MaxPacketNum )
packetnum = 1;
// cout << "************* send header: " << mypack.msg.header << endl;
int sz = mypack.byte_size() + sizeof(UniSetUDP::UDPHeader);
if( !udp->isPending(ost::Socket::pendingOutput) )
return;
size_t ret = udp->send( (char*)&(mypack.msg),sz);
if( ret < sz )
dlog[Debug::CRIT] << myname << "(send): FAILED ret=" << ret << " < sizeof=" << sz << endl;
}
// -----------------------------------------------------------------------------
void UNetSender::start()
{
if( !activated )
{
activated = true;
s_thr->start();
}
}
// -----------------------------------------------------------------------------
void UNetSender::readConfiguration()
{
xmlNode* root = conf->getXMLSensorsSection();
if(!root)
{
ostringstream err;
err << myname << "(readConfiguration): not found <sensors>";
throw SystemError(err.str());
}
UniXML_iterator it(root);
if( !it.goChildren() )
{
std::cerr << myname << "(readConfiguration): empty <sensors>?!!" << endl;
return;
}
for( ;it.getCurrent(); it.goNext() )
{
if( check_item(it) )
initItem(it);
}
}
// ------------------------------------------------------------------------------------------
bool UNetSender::check_item( UniXML_iterator& it )
{
if( s_field.empty() )
return true;
// просто проверка на не пустой field
if( s_fvalue.empty() && it.getProp(s_field).empty() )
return false;
// просто проверка что field = value
if( !s_fvalue.empty() && it.getProp(s_field)!=s_fvalue )
return false;
return true;
}
// ------------------------------------------------------------------------------------------
bool UNetSender::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
{
if( check_item(it) )
initItem(it);
return true;
}
// ------------------------------------------------------------------------------------------
bool UNetSender::initItem( UniXML_iterator& it )
{
string sname( it.getProp("name") );
string tid = it.getProp("id");
ObjectId sid;
if( !tid.empty() )
{
sid = UniSetTypes::uni_atoi(tid);
if( sid <= 0 )
sid = DefaultObjectId;
}
else
sid = conf->getSensorID(sname);
if( sid == DefaultObjectId )
{
if( dlog )
dlog[Debug::CRIT] << myname << "(readItem): ID not found for "
<< sname << endl;
return false;
}
UItem p;
p.si.id = sid;
p.si.node = conf->getLocalNode();
mypack.addData(sid,0);
p.pack_ind = mypack.size()-1;
if( maxItem >= mypack.size() )
dlist.resize(maxItem+10);
dlist[maxItem] = p;
maxItem++;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(initItem): add " << p << endl;
return true;
}
// ------------------------------------------------------------------------------------------
void UNetSender::initIterators()
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); it++ )
{
shm->initDIterator(it->dit);
shm->initAIterator(it->ait);
}
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, UNetSender::UItem& p )
{
return os << " sid=" << p.si.id;
}
// -----------------------------------------------------------------------------
#ifndef UNetSender_H_
#define UNetSender_H_
// -----------------------------------------------------------------------------
#include <ostream>
#include <string>
#include <vector>
#include <cc++/socket.h>
#include "UniSetObject_LT.h"
#include "Trigger.h"
#include "Mutex.h"
#include "SMInterface.h"
#include "SharedMemory.h"
#include "ThreadCreator.h"
#include "UDPPacket.h"
#include "UDPNReceiver.h"
// -----------------------------------------------------------------------------
/*
* Для защиты от потери пакета при переполнении "номера пакета".
* UNetReceiver при обнаружении "разрыва" в последовательнности, просто игнорирует пакет, обновляет счётчик
* и начинает обработку пока буфер опять не заполнится..
*/
class UNetSender
{
public:
UNetSender( const std::string host, const ost::tpport_t port, SMInterface* smi,
const std::string s_field="", const std::string s_fvalue="", SharedMemory* ic=0 );
~UNetSender();
struct UItem
{
UItem():
val(0)
{}
IOController_i::SensorInfo si;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniSetTypes::uniset_spin_mutex val_lock;
int pack_ind;
long val;
friend std::ostream& operator<<( std::ostream& os, UItem& p );
};
void start();
void send();
void real_send();
void update( UniSetTypes::ObjectId id, long value );
inline void setSendPause( int msec ){ sendpause = msec; }
protected:
std::string s_field;
std::string s_fvalue;
SMInterface* shm;
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
void readConfiguration();
bool check_item( UniXML_iterator& it );
private:
UNetSender();
ost::UDPBroadcast* udp;
ost::IPV4Address addr;
ost::tpport_t port;
std::string s_host;
std::string myname;
int sendpause;
bool activated;
UniSetUDP::UDPMessage mypack;
typedef std::vector<UItem> DMap;
DMap dlist;
int maxItem;
unsigned long packetnum;
ThreadCreator<UNetSender>* s_thr; // send thread
};
// -----------------------------------------------------------------------------
#endif // UNetSender_H_
// -----------------------------------------------------------------------------
#!/bin/sh
ln -s -f ../../Utilities/scripts/uniset-start.sh
ln -s -f ../../Utilities/scripts/uniset-stop.sh stop.sh
ln -s -f ../../Utilities/scripts/uniset-functions.sh
ln -s -f ../../conf/test.xml test.xml
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libUniSetUDP
Description: Support library for UniSetIOControl
Requires: libUniSetExtensions
Version: @VERSION@
Libs: -L${libdir} -lUniSetUDP
Cflags: -I${includedir}/uniset
#!/bin/sh
uniset-start.sh -f ./uniset-udpexchange --udp-name UDPExchange --udp-host 192.168.56.255 \
--udp-broadcast 1 --udp-polltime 1000 \
--confile test.xml \
--dlog-add-levels info,crit,warn
# --udp-filter-field udp --udp-filter-value 1 \
#!/bin/sh
uniset-start.sh -f ./uniset-udpexchange --udp-name UDPExchange2 --udp-host localhost --udp-port 2049 \
--confile test.xml \
--udp-filter-field udp --udp-filter-value 2 \
--udp-ip \
--dlog-add-levels info,crit,warn
#!/bin/sh
uniset-start.sh -f ./uniset-udpreceiver --udp-name UDPExchange \
--udp-host 192.168.56.255 --udp-port 3000 \
--confile test.xml \
--udp-filter-field udp --udp-filter-value 1 \
--dlog-add-levels info,crit,warn
#!/bin/sh
uniset-start.sh -f ./uniset-udpsender --udp-name UDPExchange \
--udp-host 192.168.56.255 --udp-port 2050 --udp-broadcast 1\
--udp-sendtime 2000 \
--confile test.xml \
--dlog-add-levels info,crit,warn
# --udp-filter-field udp --udp-filter-value 1 \
#!/bin/sh
uniset-start.sh -f ./uniset-unetexchange --unet-name UNetExchange \
--confile test.xml \
--unet-filter-field rs --unet-filter-value 2 --unet-maxdifferense 40 \
--dlog-add-levels info,crit,warn
#include <sstream>
#include "ObjectsActivator.h"
#include "Extensions.h"
#include "UDPExchange.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
int main( int argc, char** argv )
{
try
{
if( argc>1 && (!strcmp(argv[1],"--help") || !strcmp(argv[1],"-h")) )
{
cout << "--smemory-id objectName - SharedMemory objectID. Default: read from <SharedMemory>" << endl;
cout << "--confile filename - configuration file. Default: configure.xml" << endl;
cout << "--udp-logfile filename - logfilename. Default: udpexchange.log" << endl;
cout << endl;
UDPExchange::help_print(argc,argv);
return 0;
}
string confile=UniSetTypes::getArgParam("--confile",argc,argv,"configure.xml");
conf = new Configuration( argc, argv, confile );
string logfilename(conf->getArgParam("--udp-logfile"));
if( logfilename.empty() )
logfilename = "udpexchange.log";
conf->initDebug(dlog,"dlog");
std::ostringstream logname;
string dir(conf->getLogDir());
logname << dir << logfilename;
unideb.logFile( logname.str() );
dlog.logFile( logname.str() );
ObjectId shmID = DefaultObjectId;
string sID = conf->getArgParam("--smemory-id");
if( !sID.empty() )
shmID = conf->getControllerID(sID);
else
shmID = getSharedMemoryID();
if( shmID == DefaultObjectId )
{
cerr << sID << "? SharedMemoryID not found in " << conf->getControllersSection() << " section" << endl;
return 1;
}
UDPExchange* rs = UDPExchange::init_udpexchange(argc,argv,shmID);
if( !rs )
{
dlog[Debug::CRIT] << "(udpexchange): init не прошёл..." << endl;
return 1;
}
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(rs));
SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() );
unideb(Debug::ANY) << "\n\n\n";
unideb[Debug::ANY] << "(main): -------------- UDP Exchange START -------------------------\n\n";
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- UDP Exchange START -------------------------\n\n";
act.run(false);
// msleep(500);
// rs->execute();
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << "(udpexchange): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << "(udpexchange): catch ..." << std::endl;
}
return 0;
}
#include <sstream>
#include "ObjectsActivator.h"
#include "Extensions.h"
#include "UDPReceiver.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
int main( int argc, char** argv )
{
try
{
if( argc>1 && (!strcmp(argv[1],"--help") || !strcmp(argv[1],"-h")) )
{
cout << "--smemory-id objectName - SharedMemory objectID. Default: read from <SharedMemory>" << endl;
cout << "--confile filename - configuration file. Default: configure.xml" << endl;
cout << "--udp-logfile filename - logfilename. Default: udpexchange.log" << endl;
cout << endl;
UDPReceiver::help_print(argc,argv);
return 0;
}
string confile=UniSetTypes::getArgParam("--confile",argc,argv,"configure.xml");
conf = new Configuration( argc, argv, confile );
string logfilename(conf->getArgParam("--udp-logfile"));
if( logfilename.empty() )
logfilename = "udpexchange.log";
conf->initDebug(dlog,"dlog");
std::ostringstream logname;
string dir(conf->getLogDir());
logname << dir << logfilename;
unideb.logFile( logname.str() );
dlog.logFile( logname.str() );
ObjectId shmID = DefaultObjectId;
string sID = conf->getArgParam("--smemory-id");
if( !sID.empty() )
shmID = conf->getControllerID(sID);
else
shmID = getSharedMemoryID();
if( shmID == DefaultObjectId )
{
cerr << sID << "? SharedMemoryID not found in " << conf->getControllersSection() << " section" << endl;
return 1;
}
UDPReceiver* udp = UDPReceiver::init_udpreceiver(argc,argv,shmID);
if( !udp )
{
dlog[Debug::CRIT] << "(udpreceiver): init не прошёл..." << endl;
return 1;
}
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(udp));
SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() );
unideb(Debug::ANY) << "\n\n\n";
unideb[Debug::ANY] << "(main): -------------- UDPRecevier START -------------------------\n\n";
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- UDPReceiver START -------------------------\n\n";
act.run(false);
// msleep(500);
// rs->execute();
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << "(udpexchange): " << ex << std::endl;
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << s.str() << endl;
}
catch(...)
{
dlog[Debug::CRIT] << "(udpexchange): catch ..." << std::endl;
}
return 0;
}
#include <sstream>
#include "ObjectsActivator.h"
#include "Extensions.h"
#include "UDPSender.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
int main( int argc, char** argv )
{
try
{
if( argc>1 && (!strcmp(argv[1],"--help") || !strcmp(argv[1],"-h")) )
{
cout << "--smemory-id objectName - SharedMemory objectID. Default: read from <SharedMemory>" << endl;
cout << "--confile filename - configuration file. Default: configure.xml" << endl;
cout << "--udp-logfile filename - logfilename. Default: udpexchange.log" << endl;
cout << endl;
UDPSender::help_print(argc,argv);
return 0;
}
string confile=UniSetTypes::getArgParam("--confile",argc,argv,"configure.xml");
conf = new Configuration( argc, argv, confile );
string logfilename(conf->getArgParam("--udp-logfile"));
if( logfilename.empty() )
logfilename = "udpexchange.log";
conf->initDebug(dlog,"dlog");
std::ostringstream logname;
string dir(conf->getLogDir());
logname << dir << logfilename;
unideb.logFile( logname.str() );
dlog.logFile( logname.str() );
ObjectId shmID = DefaultObjectId;
string sID = conf->getArgParam("--smemory-id");
if( !sID.empty() )
shmID = conf->getControllerID(sID);
else
shmID = getSharedMemoryID();
if( shmID == DefaultObjectId )
{
cerr << sID << "? SharedMemoryID not found in " << conf->getControllersSection() << " section" << endl;
return 1;
}
UDPSender* udp = UDPSender::init_udpsender(argc,argv,shmID);
if( !udp )
{
dlog[Debug::CRIT] << "(udpsender): init не прошёл..." << endl;
return 1;
}
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(udp));
SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() );
unideb(Debug::ANY) << "\n\n\n";
unideb[Debug::ANY] << "(main): -------------- UDPSender START -------------------------\n\n";
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- UDPSender START -------------------------\n\n";
act.run(false);
// msleep(500);
// rs->execute();
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << "(udpsender): " << ex << std::endl;
}
catch( ost::SockException& e )
{
dlog[Debug::CRIT] << "(udpsender): " << e.getSystemErrorString() << endl;
}
catch(...)
{
dlog[Debug::CRIT] << "(udpsender): catch ..." << std::endl;
}
return 0;
}
#include <sstream>
#include "ObjectsActivator.h"
#include "Extensions.h"
#include "UNetExchange.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
int main( int argc, char** argv )
{
try
{
if( argc>1 && (!strcmp(argv[1],"--help") || !strcmp(argv[1],"-h")) )
{
cout << "--smemory-id objectName - SharedMemory objectID. Default: read from <SharedMemory>" << endl;
cout << "--confile filename - configuration file. Default: configure.xml" << endl;
cout << "--unet-logfile filename - logfilename. Default: udpexchange.log" << endl;
cout << endl;
UNetExchange::help_print(argc,argv);
return 0;
}
string confile=UniSetTypes::getArgParam("--confile",argc,argv,"configure.xml");
conf = new Configuration( argc, argv, confile );
string logfilename(conf->getArgParam("--unet-logfile"));
if( logfilename.empty() )
logfilename = "udpexchange.log";
conf->initDebug(dlog,"dlog");
std::ostringstream logname;
string dir(conf->getLogDir());
logname << dir << logfilename;
unideb.logFile( logname.str() );
dlog.logFile( logname.str() );
ObjectId shmID = DefaultObjectId;
string sID = conf->getArgParam("--smemory-id");
if( !sID.empty() )
shmID = conf->getControllerID(sID);
else
shmID = getSharedMemoryID();
if( shmID == DefaultObjectId )
{
cerr << sID << "? SharedMemoryID not found in " << conf->getControllersSection() << " section" << endl;
return 1;
}
UNetExchange* unet = UNetExchange::init_unetexchange(argc,argv,shmID);
if( !unet )
{
dlog[Debug::CRIT] << "(unetexchange): init failed.." << endl;
return 1;
}
ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(unet));
SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() );
unideb(Debug::ANY) << "\n\n\n";
unideb[Debug::ANY] << "(main): -------------- UDPRecevier START -------------------------\n\n";
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- UDPReceiver START -------------------------\n\n";
act.run(false);
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << "(unetexchange): " << ex << std::endl;
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << s.str() << endl;
}
catch(...)
{
dlog[Debug::CRIT] << "(unetexchange): catch ..." << std::endl;
}
return 0;
}
bin_PROGRAMS = @PACKAGE@-unetexchange
bin_PROGRAMS = @PACKAGE@-unetexchange @PACKAGE@-unet2-tester
# не забывайте править версию в pc-файле
UNET2_VER=@LIBVER@
......@@ -19,6 +19,11 @@ libUniSetUNet2_la_SOURCES = UDPPacket.cc UNetReceiver.cc UNetSender.cc UNetExch
$(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_unetexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS)
@PACKAGE@_unet2_tester_SOURCES = UDPPacket.cc unet2-tester.cc
@PACKAGE@_unet2_tester_LDADD = $(COMCPP_LIBS)
@PACKAGE@_unet2_tester_CXXFLAGS = $(COMCPP_CFLAGS)
# install
devel_include_HEADERS = *.h
devel_includedir = $(pkgincludedir)/extensions
......@@ -27,4 +32,4 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libUniSetUNet2.pc
all-local:
ln -sf ../UDPExchange/$(devel_include_HEADERS) ../include
ln -sf ../UNet2/$(devel_include_HEADERS) ../include
......@@ -8,38 +8,181 @@ std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPHeader& p )
return os << "nodeID=" << p.nodeID
<< " procID=" << p.procID
<< " dcount=" << p.dcount
<< " acount=" << p.acount
<< " pnum=" << p.num;
}
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPData& p )
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPHeader* p )
{
return os << (*p);
}
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPAData& p )
{
return os << "id=" << p.id << " val=" << p.val;
}
// -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPMessage& p )
{
os << (UDPHeader*)(&p) << endl;
os << "DIGITAL:" << endl;
for( size_t i=0; i<p.dcount; i++ )
os << "[" << i << "]={" << p.dID(i) << "," << p.dValue(i) << "}" << endl;
os << "ANALOG:" << endl;
for( size_t i=0; i<p.acount; i++ )
os << "[" << i << "]={" << p.a_dat[i].id << "," << p.a_dat[i].val << "}" << endl;
return os;
}
// -----------------------------------------------------------------------------
UDPMessage::UDPMessage():
count(0)
UDPMessage::UDPMessage()
{
}
// -----------------------------------------------------------------------------
bool UDPMessage::addData( const UniSetUDP::UDPData& dat )
size_t UDPMessage::addAData( const UniSetUDP::UDPAData& dat )
{
if( count >= MaxDataCount )
if( acount >= MaxACount )
return MaxACount;
a_dat[acount] = dat;
acount++;
return acount-1;
}
// -----------------------------------------------------------------------------
size_t UDPMessage::addAData( long id, long val)
{
UDPAData d(id,val);
return addAData(d);
}
// -----------------------------------------------------------------------------
bool UDPMessage::setAData( size_t index, long val )
{
if( index < MaxACount )
{
a_dat[index].val = val;
return true;
}
return false;
}
// -----------------------------------------------------------------------------
size_t UDPMessage::addDData( long id, bool val )
{
if( dcount >= MaxDCount )
return MaxDCount;
// сохраняем ID
d_id[dcount] = id;
bool res = setDData( dcount, val );
if( res )
{
dcount++;
return dcount-1;
}
return MaxDCount;
}
// -----------------------------------------------------------------------------
bool UDPMessage::setDData( size_t index, bool val )
{
if( index >= MaxDCount )
return false;
msg.dat[count] = dat;
count++;
msg.header.dcount = count;
return true;
size_t nbyte = index / sizeof(unsigned char);
size_t nbit = index % sizeof(unsigned char);
// выставляем бит
unsigned char d = d_dat[nbyte];
if( val )
d |= (1<<nbit);
else
d &= ~(1<<nbit);
d_dat[nbyte] = d;
return true;
}
// -----------------------------------------------------------------------------
long UDPMessage::dID( size_t index )
{
if( index >= MaxDCount )
return UniSetTypes::DefaultObjectId;
return d_id[index];
}
// -----------------------------------------------------------------------------
bool UDPMessage::dValue( size_t index )
{
if( index >= MaxDCount )
return UniSetTypes::DefaultObjectId;
size_t nbyte = index / sizeof(unsigned char);
size_t nbit = index % sizeof(unsigned char);
return ( d_dat[nbyte] & (1<<nbit) );
}
// -----------------------------------------------------------------------------
bool UDPMessage::addData( long id, long val)
size_t UDPMessage::transport_msg( UDPPacket& p )
{
UDPData d(id,val);
return addData(d);
memset(&p,0,sizeof(UDPPacket));
size_t i = 0;
memcpy(&(p.data[i]),this,sizeof(UDPHeader));
i += sizeof(UDPHeader);
// копируем аналоговые данные
size_t sz = acount*sizeof(UDPAData);
memcpy(&(p.data[i]),a_dat,sz);
i += sz;
// копируем булеве индексы
sz = dcount*sizeof(long);
memcpy(&(p.data[i]),d_id,sz);
i += sz;
// копируем булевые данные
size_t nbyte = dcount / sizeof(unsigned char);
size_t nbit = dcount % sizeof(unsigned char);
sz = nbit > 0 ? nbyte + 1 : nbyte;
memcpy(&(p.data[i]),d_dat,sz);
i += sz;
p.len = i;
return i;
}
// -----------------------------------------------------------------------------
UDPMessage::UDPMessage( UDPPacket& p )
{
getMessage(*this,p);
}
// -----------------------------------------------------------------------------
size_t UDPMessage::getMessage( UDPMessage& m, UDPPacket& p )
{
memset(&m,0,sizeof(m));
size_t i = 0;
memcpy(&m,&(p.data[i]),sizeof(UDPHeader));
i += sizeof(UDPHeader);
// копируем аналоговые данные
size_t sz = m.acount*sizeof(UDPAData);
memcpy(m.a_dat,&(p.data[i]),sz);
i += sz;
// копируем булеве индексы
sz = m.dcount*sizeof(long);
memcpy(m.d_id,&(p.data[i]),sz);
i += sz;
// копируем булевые данные
size_t nbyte = m.dcount / sizeof(unsigned char);
size_t nbit = m.dcount % sizeof(unsigned char);
sz = nbit > 0 ? nbyte + 1 : nbyte;
memcpy(m.d_dat,&(p.data[i]),sz);
return i+sz;
}
// -----------------------------------------------------------------------------
......@@ -8,59 +8,85 @@
// -----------------------------------------------------------------------------
namespace UniSetUDP
{
/*! Для оптимизации размера передаваемх данных, но с учёто того, что ID могут идти не подряд.
Сделан следующие формат.
Для аналоговых величин передаётся массив пар "id-value".
Для булевых величин - отдельно массив ID и отдельно битовый массив со значениями,
(по количеству битов такого же размера).
*/
struct UDPHeader
{
UDPHeader():num(0),nodeID(0),procID(0),dcount(0){}
UDPHeader():num(0),nodeID(0),procID(0),dcount(0),acount(0){}
unsigned long num;
long nodeID;
long procID;
size_t dcount;
size_t dcount; /*!< количество булевых величин */
size_t acount; /*!< количество аналоговых величин */
friend std::ostream& operator<<( std::ostream& os, UDPHeader& p );
friend std::ostream& operator<<( std::ostream& os, UDPHeader* p );
}__attribute__((packed));
static unsigned long MaxPacketNum = std::numeric_limits<unsigned long>::max();
struct UDPData
struct UDPAData
{
UDPData():id(UniSetTypes::DefaultObjectId),val(0){}
UDPData(long id, long val):id(id),val(val){}
UDPAData():id(UniSetTypes::DefaultObjectId),val(0){}
UDPAData(long id, long val):id(id),val(val){}
long id;
long val;
friend std::ostream& operator<<( std::ostream& os, UDPData& p );
friend std::ostream& operator<<( std::ostream& os, UDPAData& p );
}__attribute__((packed));
static const size_t MaxACount = 100;
static const size_t MaxDCount = 256;
static const size_t MaxDDataCount = MaxDCount / sizeof(unsigned char);
static const int MaxDataLen = 8192;
static const int MaxDataCount = ( MaxDataLen - sizeof(UniSetUDP::UDPHeader) ) / sizeof(UDPData);
struct UDPPacket
{
UDPPacket():len(0){}
struct DataPacket
{
UDPHeader header;
UDPData dat[MaxDataCount];
}__attribute__((packed));
int len;
unsigned char data[ sizeof(UDPHeader) + MaxDCount*sizeof(long) + MaxDDataCount + MaxACount*sizeof(UDPAData) ];
}__attribute__((packed));
static const int MaxDataLen = sizeof(UDPPacket);
struct UDPMessage:
public UDPHeader
{
UDPMessage();
bool addData( const UDPData& dat );
bool addData( long id, long val );
UDPMessage( UDPPacket& p );
size_t transport_msg( UDPPacket& p );
static size_t getMessage( UDPMessage& m, UDPPacket& p );
inline bool isFull(){ return count<MaxDataCount; }
inline int size(){ return count; }
inline int byte_size(){ return count*sizeof(UDPData); }
size_t addDData( long id, bool val );
bool setDData( size_t index, bool val );
long dID( size_t index );
bool dValue( size_t index );
DataPacket msg;
int count;
size_t addAData( const UDPAData& dat );
size_t addAData( long id, long val );
bool setAData( size_t index, long val );
inline bool isFull(){ return ((dcount<MaxDCount) && (acount<MaxACount)); }
inline int dsize(){ return dcount; }
inline int asize(){ return acount; }
// inline int byte_size(){ return (dcount*sizeof(long)*UDPDData) + acount*sizeof(UDPAData)); }
// количество байт в пакете с булевыми переменными...
int d_byte(){ return dcount*sizeof(long) + dcount; }
UDPAData a_dat[MaxACount]; /*!< аналоговые величины */
long d_id[MaxDCount]; /*!< список дискретных ID */
unsigned char d_dat[MaxDDataCount]; /*!< битовые значения */
friend std::ostream& operator<<( std::ostream& os, UDPMessage& p );
};
}
// -----------------------------------------------------------------------------
#endif // UDPPacket_H_
......
......@@ -14,6 +14,39 @@
#include "UNetReceiver.h"
#include "UNetSender.h"
// -----------------------------------------------------------------------------
/*!
\page pageUNetExchange2 Сетевой обмен на основе UDP (UNet2)
\par Обмен построен на основе протокола UDP.
Основная идея заключается в том, что каждый узел на порту равном своему ID
посылает в сеть UDP-пакеты содержащие данные считанные из локальной SM. Формат данных - это набор
пар "id - value". Другие узлы принимают их. Помимо этого процесс, данный процесс запускает
по потоку приёма для каждого другого узла и ловит пакеты от них, сохраняя данные в SM.
\par При своём старте процесс считывает из секции <nodes> список узлов с которыми необходимо вести обмен.
Открывает по потоку приёма на каждый узел и поток передачи для своих данных. А так же параметры
своего узла.
\par Пример конфигурирования
По умолчанию при считывании используются свойства \a ip и \a id - в качестве порта.
Но можно переопределять эти параметры, при помощи указания \a unet_port и/или \a unet_ip.
Помимо этого можно задать broadcast-адрес по умолчанию \a unet_ip для всех узлов в
свойствах секции <nodes unet_ip="xxx.255">
\code
<nodes port="2809" unet_ip="192.168.56.255">
<item ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="1" unet_port="3000" unet_ip="192.168.56.1">
<iocards>
...
</iocards>
</item>
<item ip="192.168.56.10" name="Node1" textname="Node1" unet_port="3001" unet_ip="192.168.56.2"/>
<item ip="192.168.56.11" name="Node2" textname="Node2" unet_port="3002" unet_ip="192.168.56.3"/>
</nodes>
\endcode
*/
// -----------------------------------------------------------------------------
class UNetExchange:
public UniSetObject_LT
{
......@@ -22,11 +55,11 @@ class UNetExchange:
virtual ~UNetExchange();
/*! глобальная функция для инициализации объекта */
static UNetExchange* init_unetexchange( int argc, char* argv[],
static UNetExchange* init_unetexchange( int argc, const char* argv[],
UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */
static void help_print( int argc, char* argv[] );
static void help_print( int argc, const char* argv[] );
bool checkExistUNetHost( const std::string host, ost::tpport_t port );
......@@ -53,7 +86,6 @@ class UNetExchange:
void initIterators();
void startReceivers();
void initSender( const std::string host, const ost::tpport_t port, UniXML_iterator& it );
enum Timer
{
......
......@@ -53,6 +53,7 @@ class UNetReceiver
~UNetReceiver();
void start();
void stop();
void receive();
void update();
......@@ -114,6 +115,7 @@ class UNetReceiver
typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue;
PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */
UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очереlного сообщения */
UniSetUDP::UDPPacket r_buf;
UniSetTypes::uniset_mutex packMutex; /*!< mutex для работы с очередью */
unsigned long pnum; /*!< текущий номер обработанного сообщения, для проверки непрерывности последовательности пакетов */
......@@ -134,13 +136,21 @@ class UNetReceiver
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniversalIO::IOTypes iotype;
ItemInfo():
id(UniSetTypes::DefaultObjectId),
iotype(UniversalIO::UnknownIOType){}
};
typedef std::vector<ItemInfo> ItemVec;
ItemVec icache; /*!< кэш итераторов */
bool cache_init_ok;
void initCache( UniSetUDP::UDPMessage& pack, bool force=false );
ItemVec d_icache; /*!< кэш итераторов для булевых */
ItemVec a_icache; /*!< кэш итераторов для аналоговых */
bool d_cache_init_ok;
bool a_cache_init_ok;
void initDCache( UniSetUDP::UDPMessage& pack, bool force=false );
void initACache( UniSetUDP::UDPMessage& pack, bool force=false );
};
// -----------------------------------------------------------------------------
#endif // UNetReceiver_H_
......
......@@ -36,16 +36,24 @@ s_thr(0)
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UNetSender): UDP set to " << s_host << ":" << port << endl;
ost::Thread::setException(ost::Thread::throwException);
try
{
addr = s_host.c_str();
udp = new ost::UDPBroadcast(addr,port);
}
catch( ost::SockException& e )
catch( std::exception& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString() << endl;
s << myname << ": " << e.what();
dlog[Debug::CRIT] << s.str() << std::endl;
throw SystemError(s.str());
}
catch( ... )
{
ostringstream s;
s << myname << ": catch...";
dlog[Debug::CRIT] << s.str() << std::endl;
throw SystemError(s.str());
}
......@@ -63,8 +71,8 @@ s_thr(0)
// выставляем поля, которые не меняются
mypack.msg.header.nodeID = conf->getLocalNode();
mypack.msg.header.procID = shm->ID();
mypack.nodeID = conf->getLocalNode();
mypack.procID = shm->ID();
}
// -----------------------------------------------------------------------------
UNetSender::~UNetSender()
......@@ -74,17 +82,55 @@ UNetSender::~UNetSender()
delete shm;
}
// -----------------------------------------------------------------------------
void UNetSender::update( UniSetTypes::ObjectId id, long value )
void UNetSender::updateFromSM()
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
if( it->si.id == id )
long value = 0;
if( it->iotype == UniversalIO::DigitalInput || it->iotype == UniversalIO::DigitalOutput )
value = shm->localGetState(it->dit,it->id) ? 1 : 0;
else if( it->iotype == UniversalIO::AnalogInput || it->iotype == UniversalIO::AnalogOutput )
value = shm->localGetValue(it->ait,it->id);
else
{
uniset_spin_lock lock(it->val_lock);
it->val = value;
dlog[Debug::CRIT] << myname << "(update): Unknown iotype for sid=" << it->id << endl;
continue;
}
break;
updateItem(it,value);
}
}
// -----------------------------------------------------------------------------
void UNetSender::updateSensor( UniSetTypes::ObjectId id, long value )
{
// cerr << myname << ": UPDATE SENSOR id=" << id << " value=" << value << endl;
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
if( it->id == id )
{
updateItem( it, value );
break;
}
}
}
// -----------------------------------------------------------------------------
void UNetSender::updateItem( DMap::iterator& it, long value )
{
if( it == dlist.end() )
return;
if( it->iotype == UniversalIO::DigitalInput || it->iotype == UniversalIO::DigitalOutput )
{
UniSetTypes::uniset_mutex_lock l(pack_mutex,100);
mypack.setDData(it->pack_ind,value);
}
else if( it->iotype == UniversalIO::AnalogInput || it->iotype == UniversalIO::AnalogOutput )
{
UniSetTypes::uniset_mutex_lock l(pack_mutex,100);
mypack.setAData(it->pack_ind,value);
}
}
// -----------------------------------------------------------------------------
......@@ -110,42 +156,56 @@ void UNetSender::send()
{
try
{
if( !shm->isLocalwork() )
updateFromSM();
real_send();
}
catch( ost::SockException& e )
{
cerr << myname << "(send): " << e.getString() << endl;
dlog[Debug::WARN] << myname << "(send): " << e.getString() << endl;
}
catch( UniSetTypes::Exception& ex)
{
cerr << myname << "(send): " << ex << std::endl;
dlog[Debug::WARN] << myname << "(send): " << ex << std::endl;
}
catch( std::exception& e )
{
dlog[Debug::WARN] << myname << "(send): " << e.what() << std::endl;
}
catch(...)
{
cerr << myname << "(send): catch ..." << std::endl;
dlog[Debug::WARN] << myname << "(send): catch ..." << std::endl;
}
msleep(sendpause);
}
cerr << "************* execute FINISH **********" << endl;
dlog[Debug::INFO] << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UNetSender::real_send()
{
mypack.msg.header.num = packetnum++;
UniSetTypes::uniset_mutex_lock l(pack_mutex,300);
mypack.num = packetnum++;
if( packetnum > UniSetUDP::MaxPacketNum )
packetnum = 1;
// cout << "************* send header: " << mypack.msg.header << endl;
size_t sz = mypack.byte_size() + sizeof(UniSetUDP::UDPHeader);
if( !udp->isPending(ost::Socket::pendingOutput) )
return;
size_t ret = udp->send( (char*)&(mypack.msg),sz);
if( ret < sz )
dlog[Debug::CRIT] << myname << "(real_send): FAILED ret=" << ret << " < sizeof=" << sz << endl;
mypack.transport_msg(s_msg);
size_t ret = udp->send( (char*)s_msg.data,s_msg.len );
if( ret < s_msg.len )
dlog[Debug::CRIT] << myname << "(real_send): FAILED ret=" << ret << " < sizeof=" << s_msg.len << endl;
}
// -----------------------------------------------------------------------------
void UNetSender::stop()
{
activated = false;
// s_thr->stop();
}
// -----------------------------------------------------------------------------
void UNetSender::start()
......@@ -208,7 +268,7 @@ bool UNetSender::initItem( UniXML_iterator& it )
{
string sname( it.getProp("name") );
string tid = it.getProp("id");
string tid(it.getProp("id"));
ObjectId sid;
if( !tid.empty() )
......@@ -229,12 +289,40 @@ bool UNetSender::initItem( UniXML_iterator& it )
}
UItem p;
p.si.id = sid;
p.si.node = conf->getLocalNode();
mypack.addData(sid,0);
p.pack_ind = mypack.size()-1;
p.iotype = UniSetTypes::getIOType(it.getProp("iotype"));
if( p.iotype == UniversalIO::UnknownIOType )
{
dlog[Debug::CRIT] << myname << "(readItem): Unknown iotype for sid=" << sid << endl;
return false;
}
p.id = sid;
if( maxItem >= mypack.size() )
if( p.iotype == UniversalIO::DigitalInput || p.iotype == UniversalIO::DigitalOutput )
{
p.pack_ind = mypack.addDData(sid,0);
if ( p.pack_ind >= UniSetUDP::MaxDCount )
{
dlog[Debug::CRIT] << myname
<< "(readItem): OVERFLOW! MAX UDP DIGITAL DATA LIMIT! max="
<< UniSetUDP::MaxDCount << endl;
return false;
}
}
else if( p.iotype == UniversalIO::AnalogInput || p.iotype == UniversalIO::AnalogOutput )
{
p.pack_ind = mypack.addAData(sid,0);
if ( p.pack_ind >= UniSetUDP::MaxACount )
{
dlog[Debug::CRIT] << myname
<< "(readItem): OVERFLOW! MAX UDP ANALOG DATA LIMIT! max="
<< UniSetUDP::MaxACount << endl;
return false;
}
}
if( maxItem >= dlist.size() )
dlist.resize(maxItem+10);
dlist[maxItem] = p;
......@@ -247,6 +335,11 @@ bool UNetSender::initItem( UniXML_iterator& it )
}
// ------------------------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, UNetSender::UItem& p )
{
return os << " sid=" << p.id;
}
// -----------------------------------------------------------------------------
void UNetSender::initIterators()
{
DMap::iterator it=dlist.begin();
......@@ -257,8 +350,10 @@ void UNetSender::initIterators()
}
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, UNetSender::UItem& p )
void UNetSender::askSensors( UniversalIO::UIOCommand cmd )
{
return os << " sid=" << p.si.id;
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); it++ )
shm->askSensor(it->id,cmd);
}
// -----------------------------------------------------------------------------
......@@ -29,27 +29,44 @@ class UNetSender
struct UItem
{
UItem():
val(0)
{}
iotype(UniversalIO::UnknownIOType),
id(UniSetTypes::DefaultObjectId),
pack_ind(-1){}
IOController_i::SensorInfo si;
UniversalIO::IOTypes iotype;
UniSetTypes::ObjectId id;
IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit;
UniSetTypes::uniset_spin_mutex val_lock;
int pack_ind;
long val;
friend std::ostream& operator<<( std::ostream& os, UItem& p );
};
typedef std::vector<UItem> DMap;
void start();
void stop();
void send();
void real_send();
void update( UniSetTypes::ObjectId id, long value );
/*! (принудительно) обновить все данные (из SM) */
void updateFromSM();
/*! Обновить значение по ID датчика */
void updateSensor( UniSetTypes::ObjectId id, long value );
/*! Обновить значение по итератору */
void updateItem( DMap::iterator& it, long value );
inline void setSendPause( int msec ){ sendpause = msec; }
/*! заказать датчики */
void askSensors( UniversalIO::UIOCommand cmd );
/*! инициализация итераторов */
void initIterators();
protected:
std::string s_field;
......@@ -57,7 +74,6 @@ class UNetSender
SMInterface* shm;
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
......@@ -76,11 +92,12 @@ class UNetSender
int sendpause;
bool activated;
UniSetTypes::uniset_mutex pack_mutex;
UniSetUDP::UDPMessage mypack;
typedef std::vector<UItem> DMap;
DMap dlist;
int maxItem;
unsigned long packetnum;
UniSetUDP::UDPPacket s_msg;
ThreadCreator<UNetSender>* s_thr; // send thread
};
......
#include <cstdlib>
#include <errno.h>
#include <getopt.h>
#include <cstring>
#include <iostream>
#include <cc++/socket.h>
#include "UDPPacket.h"
// --------------------------------------------------------------------------
static struct option longopts[] = {
{ "help", no_argument, 0, 'h' },
{ "send", required_argument, 0, 's' },
{ "receive", required_argument, 0, 'r' },
{ "proc-id", required_argument, 0, 'p' },
{ "node-id", required_argument, 0, 'n' },
{ "send-pause", required_argument, 0, 'x' },
{ "timeout", required_argument, 0, 't' },
{ "data-count", required_argument, 0, 'c' },
{ "disable-broadcast", no_argument, 0, 'b' },
{ "show-data", no_argument, 0, 'd' },
{ "check-lost", no_argument, 0, 'l' },
{ "verbode", required_argument, 0, 'v' },
{ "num-cycles", required_argument, 0, 'z' },
{ NULL, 0, 0, 0 }
};
// --------------------------------------------------------------------------
using namespace std;
using namespace UniSetUDP;
// --------------------------------------------------------------------------
enum Command
{
cmdNOP,
cmdSend,
cmdReceive
};
// --------------------------------------------------------------------------
static bool split_addr( const string addr, string& host, ost::tpport_t& port )
{
string::size_type pos = addr.rfind(':');
if( pos != string::npos )
{
host = addr.substr(0,pos);
string s_port(addr.substr(pos+1,addr.size()-1));
port = UniSetTypes::uni_atoi(s_port.c_str());
return true;
}
return false;
}
// --------------------------------------------------------------------------
int main(int argc, char* argv[])
{
int optindex = 0;
int opt = 0;
Command cmd = cmdNOP;
int verb = 0;
std::string addr = "";
ost::tpport_t port=0;
int usecpause = 2000000;
timeout_t tout = TIMEOUT_INF;
bool broadcast = true;
int procID = 1;
int nodeID = 1;
size_t count = 50;
bool lost = false;
bool show = false;
int ncycles = -1;
while( (opt = getopt_long(argc, argv, "hs:c:r:p:n:t:x:blvdz:",longopts,&optindex)) != -1 )
{
switch (opt)
{
case 'h':
cout << "-h|--help - this message" << endl;
cout << "[-s|--send] host:port - Send message." << endl;
cout << "[-c|--data-count] num - Send num count of value. Default: 50." << endl;
cout << "[-r|--receive] host:port - Receive message." << endl;
cout << "[-p|--proc-id] id - Set packet header. From 'procID'. Default: 1" << endl;
cout << "[-n|--node-id] id - Set packet header. From 'nodeID'. Default: 1" << endl;
cout << "[-t|--timeout] msec - timeout for receive. Default: 0 msec (waitup)." << endl;
cout << "[-x|--send-pause] msec - pause for send packets. Default: 200 msec." << endl;
cout << "[-b|--disable-broadcast] - Disable broadcast mode." << endl;
cout << "[-l|--check-lost] - Check the lost packets." << endl;
cout << "[-v|--verbose] - verbose mode." << endl;
cout << "[-d|--show-data] - show receive data." << endl;
cout << "[-z|--num-cycles] num - Number of cycles of exchange. Default: -1 - infinitely." << endl;
cout << endl;
return 0;
case 'r':
cmd = cmdReceive;
addr = string(optarg);
break;
case 's':
addr = string(optarg);
cmd = cmdSend;
break;
case 't':
tout = UniSetTypes::uni_atoi(optarg);
break;
case 'x':
usecpause = UniSetTypes::uni_atoi(optarg)*1000;
break;
case 'c':
count = UniSetTypes::uni_atoi(optarg);
break;
case 'p':
procID = UniSetTypes::uni_atoi(optarg);
break;
case 'n':
nodeID = UniSetTypes::uni_atoi(optarg);
break;
case 'b':
broadcast = false;
break;
case 'd':
show = true;
break;
case 'l':
lost = true;
break;
case 'v':
verb = 1;
break;
case 'z':
ncycles = UniSetTypes::uni_atoi(optarg);
break;
case '?':
default:
cerr << "? argumnet" << endl;
return 0;
}
}
if( cmd == cmdNOP )
{
cerr << "No command... Use -h for help" << endl;
return -1;
}
if( tout < 0 )
tout = TIMEOUT_INF;
ost::Thread::setException(ost::Thread::throwException);
try
{
string s_host;
if( !split_addr(addr,s_host,port) )
{
cerr << "(main): Unknown 'host:port' for '" << addr << "'" << endl;
return 1;
}
if( verb )
{
cout << " host=" << s_host
<< " port=" << port
<< " timeout=";
if( tout == TIMEOUT_INF )
cout << "Waitup";
else
cout << tout;
cout << " msecpause=" << usecpause/1000
<< endl;
}
ost::IPV4Host host(s_host.c_str());
// udp.UDPTransmit::setBroadcast(broadcast);
switch( cmd )
{
case cmdReceive:
{
ost::UDPDuplex udp(host,port);
// char buf[UniSetUDP::MaxDataLen];
UniSetUDP::UDPMessage pack;
UniSetUDP::UDPPacket buf;
unsigned long prev_num=1;
int nc = 1;
if( ncycles > 0 )
nc = ncycles;
while( nc )
{
try
{
if( !udp.isInputReady(tout) )
{
cout << "(recv): Timeout.." << endl;
continue;
}
size_t ret = udp.UDPReceive::receive( &(buf.data), sizeof(buf.data) );
size_t sz = UniSetUDP::UDPMessage::getMessage(pack,buf);
if( sz == 0 )
{
cerr << "(recv): FAILED header ret=" << ret
<< " sizeof=" << sz<< endl;
continue;
}
if( lost )
{
if( prev_num != (pack.num-1) )
cerr << "WARNING! Incorrect sequence of packets! current=" << pack.num
<< " prev=" << prev_num << endl;
prev_num = pack.num;
}
// if( verb )
// cout << "receive OK. header: " << pack.msg.header
// << " bytes: " << ret << endl;
if( show )
cout << "receive data: " << pack << endl;
}
catch( ost::SockException& e )
{
cerr << "(recv): " << e.getString() << " (" << addr << ")" << endl;
}
catch( ... )
{
cerr << "(recv): catch ..." << endl;
}
if( ncycles > 0 )
{
nc--;
if( nc <=0 )
break;
}
}
}
break;
case cmdSend:
{
ost::UDPSocket* udp;
if( !broadcast )
udp = new ost::UDPSocket();
else
udp = new ost::UDPBroadcast(host,port);
UniSetUDP::UDPMessage mypack;
mypack.nodeID = nodeID;
mypack.procID = procID;
for( size_t i=0; i < count; i++ )
{
UDPAData d(i,i);
mypack.addAData(d);
}
for( int i=0; i < count; i++ )
mypack.addDData(i,i);
udp->setPeer(host,port);
unsigned long packetnum = 0;
UniSetUDP::UDPPacket s_buf;
int nc = 1;
if( ncycles > 0 )
nc = ncycles;
while( nc )
{
mypack.num = packetnum++;
if( packetnum > UniSetUDP::MaxPacketNum )
packetnum = 1;
try
{
if( udp->isPending(ost::Socket::pendingOutput,tout) )
{
mypack.transport_msg(s_buf);
if( verb )
cout << "(send): to addr=" << addr << " d_count=" << mypack.dcount
<< " a_count=" << mypack.acount << " bytes=" << s_buf.len << endl;
size_t ret = udp->send((char*)&s_buf.data, s_buf.len);
if( ret < s_buf.len )
cerr << "(send): FAILED ret=" << ret << " < sizeof=" << s_buf.len << endl;
}
}
catch( ost::SockException& e )
{
cerr << "(send): " << e.getString() << " (" << addr << ")" << endl;
}
catch( ... )
{
cerr << "(send): catch ..." << endl;
}
if( ncycles > 0 )
{
nc--;
if( nc <=0 )
break;
}
usleep(usecpause);
}
}
break;
default:
cerr << endl << "Unknown command: '" << cmd << "'. Use -h for help" << endl;
return -1;
break;
}
}
catch( std::exception& e )
{
cerr << "(main): " << e.what() << endl;
}
catch( ... )
{
cerr << "(main): catch ..." << endl;
return 1;
}
return 0;
}
// --------------------------------------------------------------------------
#include <sstream>
#include <sys/wait.h>
#include "ObjectsActivator.h"
#include "Extensions.h"
#include "UNetExchange.h"
......@@ -7,7 +8,7 @@ using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
int main( int argc, char** argv )
int main( int argc, const char** argv )
{
try
{
......@@ -21,20 +22,19 @@ int main( int argc, char** argv )
return 0;
}
string confile=UniSetTypes::getArgParam("--confile",argc,argv,"configure.xml");
conf = new Configuration( argc, argv, confile );
uniset_init(argc,argv);
string logfilename(conf->getArgParam("--unet-logfile"));
if( logfilename.empty() )
logfilename = "udpexchange.log";
conf->initDebug(dlog,"dlog");
std::ostringstream logname;
string dir(conf->getLogDir());
logname << dir << logfilename;
unideb.logFile( logname.str() );
dlog.logFile( logname.str() );
UniSetExtensions::dlog.logFile( logname.str() );
conf->initDebug(UniSetExtensions::dlog,"dlog");
ObjectId shmID = DefaultObjectId;
string sID = conf->getArgParam("--smemory-id");
......@@ -68,21 +68,17 @@ int main( int argc, char** argv )
dlog[Debug::ANY] << "(main): -------------- UDPReceiver START -------------------------\n\n";
act.run(false);
while( waitpid(-1, 0, 0) > 0 );
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << "(unetexchange): " << ex << std::endl;
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << s.str() << endl;
}
catch(...)
{
dlog[Debug::CRIT] << "(unetexchange): catch ..." << std::endl;
}
while( waitpid(-1, 0, 0) > 0 );
return 0;
}
......@@ -9,6 +9,29 @@
#include "SharedMemory.h"
#include "PassiveTimer.h"
// -----------------------------------------------------------------------------
/*!
\page pageUniExchange Обмен между узлами на основе TCP/IP (UniNet).
\par Обмен построен на основе функций IOControl-ера получения списка дискретных
и аналоговых датчиков. Работает через удалённые CORBA-вызовы.
\par Процесс считывает из конфигурационного файла список узлов которые необходимо
опрашивать (точнее список IOControl-еров), запускается поток обмена, в котором
эти узлы ПОСЛЕДОВАТЕЛЬНО опрашиваются..
\par Пример записи в конфигурационном файле для опроса пяти узлов...
\code
<UniExchange name="UniExchange">
<item name="UniExchange2" node="Node2"/>
<item id="3001" node_id="Node2"/>
<item name="UniExchange3" node="Node3"/>
<item name="UniExchange4" node="Node4"/>
<item name="UniExchange5" node="Node5"/>
</UniExchange>
\endcode
Запись можно делать по "id" или по "name"
*/
// -----------------------------------------------------------------------------
class UniExchange:
public IOController
{
......
#include <sys/wait.h>
#include <string>
#include "Debug.h"
#include "ObjectsActivator.h"
......@@ -52,6 +53,7 @@ int main(int argc, const char **argv)
act.broadcast( sm.transport_msg() );
act.run(true);
shm->execute();
while( waitpid(-1, 0, 0) > 0 );
return 0;
}
catch(SystemError& err)
......@@ -67,5 +69,6 @@ int main(int argc, const char **argv)
unideb[Debug::CRIT] << "(uninetwork): catch(...)" << endl;
}
while( waitpid(-1, 0, 0) > 0 );
return 1;
}
/* This file is part of the UniSet project
* Copyright (c) 2002 Free Software Foundation, Inc.
* Copyright (c) 2002 Pavel Vainerman
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// --------------------------------------------------------------------------
/*! \file
* \brief Реализация RepositoryAgent
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
#ifndef RepositoryAgent_H_
#define RepositoryAgent_H_
//---------------------------------------------------------------------------
#include "RepositoryAgent_i.hh"
#include "BaseProcess_i.hh"
#include "BaseProcess.h"
#include "UniSetTypes.h"
#include "ObjectIndex.h"
//----------------------------------------------------------------------------------------
/*! \class RepositoryAgent
*/
class RepositoryAgent:
public POA_RepositoryAgent_i,
public BaseProcess
{
public:
RepositoryAgent( ObjectId id, const UniSetTypes::ObjectInfo *pObjectsMap );
~RepositoryAgent();
// virtual void registration(const char* name, ::CORBA::Object_ptr ref);
// virtual void unregistration(const char* name, ::CORBA::Object_ptr ref);
virtual CORBA::Object_ptr resolve(const char* name);
virtual CORBA::Object_ptr resolveid( UniSetTypes::ObjectId id);
virtual void execute();
protected:
RepositoryAgent();
ObjectIndex oind;
private:
};
#endif
......@@ -71,6 +71,7 @@ class UniversalInterface
~UniversalInterface();
inline UniSetTypes::ObjectIndex* getObjectIndex() { return oind; }
inline UniSetTypes::Configuration* getConf() { return uconf; }
// -------- Функции работы с группой датчиков -----------
......
......@@ -127,6 +127,9 @@ class ModbusClient
*/
int setAfterSendPause( timeout_t msec );
/*! установить паузу при ожидании символа */
inline void setSleepPause( timeout_t usec ){ sleepPause_usec = usec; }
void initLog( UniSetTypes::Configuration* conf, const std::string name, const std::string logfile="" );
void setLog( DebugStream& dlog );
......@@ -172,7 +175,8 @@ class ModbusClient
ModbusRTU::ModbusMessage qbuf; /*!< буфер для посылки сообщений */
timeout_t replyTimeOut_ms; /*!< таймаут на ожидание ответа */
timeout_t aftersend_msec; /*!< пауза после посылки запроса */
timeout_t aftersend_msec; /*!< пауза после посылки запроса */
timeout_t sleepPause_usec; /*!< пауза между попытками чтения символа из канала */
bool crcNoCheckit;
......@@ -181,6 +185,8 @@ class ModbusClient
void printProcessingTime();
PassiveTimer tmProcessing;
private:
};
......
......@@ -42,6 +42,9 @@ class ModbusServer
/*! установить время ожидания по умолчанию */
void setRecvTimeout( timeout_t msec );
/*! установить паузу при ожидании символа */
inline void setSleepPause( timeout_t usec ){ sleepPause_usec = usec; }
inline void setCRCNoCheckit( bool set ){ crcNoCheckit = set; }
inline bool isCRCNoCheckit(){ return crcNoCheckit; }
......@@ -203,6 +206,7 @@ class ModbusServer
timeout_t recvTimeOut_ms; /*!< таймаут на приём */
timeout_t replyTimeout_ms; /*!< таймаут на формирование ответа */
timeout_t aftersend_msec; /*!< пауза после посылки ответа */
timeout_t sleepPause_usec; /*!< пауза между попытками чтения символа из канала */
bool onBroadcast; /*!< включен режим работы с broadcst-сообщениями */
bool crcNoCheckit;
......
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