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

Merge branch 'etersoft'

parents d7818975 ccbdc8a8
...@@ -128,7 +128,6 @@ int main(int argc, char** argv) ...@@ -128,7 +128,6 @@ int main(int argc, char** argv)
int optindex = 0; int optindex = 0;
char opt = 0; char opt = 0;
while( (opt = getopt_long(argc, argv, "hc:beomsfur:l:i:x:g:w:y:p:",longopts,&optindex)) != -1 ) while( (opt = getopt_long(argc, argv, "hc:beomsfur:l:i:x:g:w:y:p:",longopts,&optindex)) != -1 )
{ {
switch (opt) //разбираем параметры switch (opt) //разбираем параметры
...@@ -181,7 +180,7 @@ int main(int argc, char** argv) ...@@ -181,7 +180,7 @@ int main(int argc, char** argv)
case 'w': //--getRawValue case 'w': //--getRawValue
{ {
// cout<<"(main):received option --getRawValue='"<<optarg<<"'"<<endl; // cout<<"(main):received option --getRawValue='"<<optarg<<"'"<<endl;
uniset_init(argc,argv,conffile); uniset_init(argc,argv,conffile);
UniversalInterface ui(conf); UniversalInterface ui(conf);
return getRawValue(optarg,ui); return getRawValue(optarg,ui);
...@@ -289,9 +288,8 @@ int main(int argc, char** argv) ...@@ -289,9 +288,8 @@ int main(int argc, char** argv)
default: default:
{ {
short_usage(); short_usage();
return 0; return 1;
} }
} }
} }
...@@ -320,6 +318,8 @@ int main(int argc, char** argv) ...@@ -320,6 +318,8 @@ int main(int argc, char** argv)
{ {
cerr << "неизвестное исключение" << endl; cerr << "неизвестное исключение" << endl;
} }
return 1;
} }
// ============================================================================================== // ==============================================================================================
......
#!/bin/sh #!/bin/sh
./uniset-start.sh -f "./uniset-admin --confile test.xml --`basename $0 .sh` $1 $2 $3 $4" ./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) ...@@ -70,6 +70,8 @@ int main(int argc, char** argv)
act.addObject(static_cast<class UniSetObject*>(&is)); act.addObject(static_cast<class UniSetObject*>(&is));
act.run(false); act.run(false);
} }
return 0;
} }
catch(Exception& ex) catch(Exception& ex)
{ {
...@@ -80,5 +82,5 @@ int main(int argc, char** argv) ...@@ -80,5 +82,5 @@ int main(int argc, char** argv)
cerr << "(InfoServer::main): catch ..." << endl; cerr << "(InfoServer::main): catch ..." << endl;
} }
return 0; return 1;
} }
...@@ -23,13 +23,14 @@ static struct option longopts[] = { ...@@ -23,13 +23,14 @@ static struct option longopts[] = {
// { "writefile15", required_argument, 0, 'p' }, // { "writefile15", required_argument, 0, 'p' },
{ "filetransfer66", required_argument, 0, 'u' }, { "filetransfer66", required_argument, 0, 'u' },
{ "timeout", required_argument, 0, 't' }, { "timeout", required_argument, 0, 't' },
{ "autodetect-slave", no_argument, 0, 'l' }, { "autodetect-slave", no_argument, 0, 'q' },
{ "autodetect-speed", required_argument, 0, 'n' }, { "autodetect-speed", required_argument, 0, 'n' },
{ "device", required_argument, 0, 'd' }, { "device", required_argument, 0, 'd' },
{ "verbose", no_argument, 0, 'v' }, { "verbose", no_argument, 0, 'v' },
{ "myaddr", required_argument, 0, 'a' }, { "myaddr", required_argument, 0, 'a' },
{ "speed", required_argument, 0, 's' }, { "speed", required_argument, 0, 's' },
{ "use485F", no_argument, 0, 'y' }, { "use485F", no_argument, 0, 'y' },
{ "num-cycles", required_argument, 0, 'q' },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -61,6 +62,7 @@ static void print_help() ...@@ -61,6 +62,7 @@ static void print_help()
printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n"); 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("[-s|--speed] speed - 9600,14400,19200,38400,57600,115200. Default: 38400.\n");
printf("[-t|--timeout] msec - Timeout. Default: 2000.\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"); printf("[-v|--verbose] - Print all messages to stdout\n");
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -105,10 +107,11 @@ int main( int argc, char **argv ) ...@@ -105,10 +107,11 @@ int main( int argc, char **argv )
DebugStream dlog; DebugStream dlog;
string tofile(""); string tofile("");
int use485 = 0; int use485 = 0;
int ncycles = -1;
try 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) switch (opt)
{ {
...@@ -255,7 +258,7 @@ int main( int argc, char **argv ) ...@@ -255,7 +258,7 @@ int main( int argc, char **argv )
verb = 1; verb = 1;
break; break;
case 'l': case 'q':
{ {
if( cmd == cmdNOP ) if( cmd == cmdNOP )
cmd = cmdDetectSlave; cmd = cmdDetectSlave;
...@@ -297,6 +300,10 @@ int main( int argc, char **argv ) ...@@ -297,6 +300,10 @@ int main( int argc, char **argv )
} }
break; break;
case 'l':
ncycles = uni_atoi(optarg);
break;
case '?': case '?':
default: default:
printf("? argumnet\n"); printf("? argumnet\n");
...@@ -321,7 +328,11 @@ int main( int argc, char **argv ) ...@@ -321,7 +328,11 @@ int main( int argc, char **argv )
mb.setSpeed(speed); mb.setSpeed(speed);
mb.setLog(dlog); mb.setLog(dlog);
while(1) int nc = 1;
if( ncycles > 0 )
nc = ncycles;
while( nc )
{ {
try try
{ {
...@@ -579,6 +590,14 @@ int main( int argc, char **argv ) ...@@ -579,6 +590,14 @@ int main( int argc, char **argv )
cout << "timeout..." << endl; cout << "timeout..." << endl;
} }
if( ncycles > 0 )
{
nc--;
if( nc <=0 )
break;
}
msleep(200); msleep(200);
} }
} }
......
...@@ -113,9 +113,9 @@ int main( int argc, char **argv ) ...@@ -113,9 +113,9 @@ int main( int argc, char **argv )
{ {
cerr << "(mbtcpserver): " << ex << endl; cerr << "(mbtcpserver): " << ex << endl;
} }
catch( ost::SockException& e ) catch( std::exception& e )
{ {
cerr << e.getString() << ": " << e.getSystemErrorString() << endl; cerr << "(mbtcpserver): " << e.what() << endl;
} }
catch(...) catch(...)
{ {
......
...@@ -23,6 +23,7 @@ static struct option longopts[] = { ...@@ -23,6 +23,7 @@ static struct option longopts[] = {
{ "myaddr", required_argument, 0, 'a' }, { "myaddr", required_argument, 0, 'a' },
{ "port", required_argument, 0, 'p' }, { "port", required_argument, 0, 'p' },
{ "persistent-connection", no_argument, 0, 'o' }, { "persistent-connection", no_argument, 0, 'o' },
{ "num-cycles", required_argument, 0, 'l' },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -42,6 +43,7 @@ static void print_help() ...@@ -42,6 +43,7 @@ static void print_help()
printf("[-p|--port] port - Modbus server port. Default: 502.\n"); printf("[-p|--port] port - Modbus server port. Default: 502.\n");
printf("[-t|--timeout] msec - Timeout. Default: 2000.\n"); printf("[-t|--timeout] msec - Timeout. Default: 2000.\n");
printf("[-o|--persistent-connection] - Use persistent-connection.\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"); printf("[-v|--verbose] - Print all messages to stdout\n");
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -77,10 +79,11 @@ int main( int argc, char **argv ) ...@@ -77,10 +79,11 @@ int main( int argc, char **argv )
ModbusRTU::ModbusAddr slaveaddr = 0x00; ModbusRTU::ModbusAddr slaveaddr = 0x00;
int tout = 2000; int tout = 2000;
DebugStream dlog; DebugStream dlog;
int ncycles = -1;
try 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) switch (opt)
{ {
...@@ -182,6 +185,10 @@ int main( int argc, char **argv ) ...@@ -182,6 +185,10 @@ int main( int argc, char **argv )
persist = true; persist = true;
break; break;
case 'l':
ncycles = uni_atoi(optarg);
break;
case '?': case '?':
default: default:
printf("? argumnet\n"); printf("? argumnet\n");
...@@ -216,7 +223,11 @@ int main( int argc, char **argv ) ...@@ -216,7 +223,11 @@ int main( int argc, char **argv )
if( count > ModbusRTU::MAXDATALEN && verb ) if( count > ModbusRTU::MAXDATALEN && verb )
cout << "Too long packet! Max count=" << ModbusRTU::MAXDATALEN << " (ignore...)" << endl; cout << "Too long packet! Max count=" << ModbusRTU::MAXDATALEN << " (ignore...)" << endl;
while(1) int nc = 1;
if( ncycles > 0 )
nc = ncycles;
while( nc )
{ {
try try
{ {
...@@ -406,7 +417,15 @@ int main( int argc, char **argv ) ...@@ -406,7 +417,15 @@ int main( int argc, char **argv )
cout << "timeout..." << endl; cout << "timeout..." << endl;
} }
if( ncycles > 0 )
{
nc--;
if( nc <=0 )
break;
}
msleep(200); msleep(200);
} // end of while } // end of while
mb.disconnect(); mb.disconnect();
...@@ -423,9 +442,9 @@ int main( int argc, char **argv ) ...@@ -423,9 +442,9 @@ int main( int argc, char **argv )
{ {
cerr << "(mbtester): " << ex << endl; cerr << "(mbtester): " << ex << endl;
} }
catch( ost::SockException& e ) catch( std::exception& e )
{ {
cerr << e.getString() << ": " << e.getSystemErrorString() << endl; cerr << "(mbtester): " << e.what() << endl;
} }
catch(...) catch(...)
{ {
......
...@@ -2,16 +2,10 @@ ...@@ -2,16 +2,10 @@
# This file is part of the UniSet library # # 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 InfoServer SMonit MBTester codegen SImitator
#MapSourceParser ClassGen #MapSourceParser ClassGen
if DISABLE_MYSQL
SUBDIRS = ${UTILS}
else
SUBDIRS = ${UTILS} DBServer-MySQL
endif
include $(top_builddir)/conf/common.mk include $(top_builddir)/conf/common.mk
......
...@@ -77,6 +77,7 @@ int main(int argc, char** argv) ...@@ -77,6 +77,7 @@ int main(int argc, char** argv)
ObjectsActivator act; ObjectsActivator act;
act.addObject(static_cast<class UniSetObject*>(&nc)); act.addObject(static_cast<class UniSetObject*>(&nc));
act.run(false); act.run(false);
return 0;
} }
catch(Exception& ex) catch(Exception& ex)
{ {
...@@ -87,5 +88,5 @@ int main(int argc, char** argv) ...@@ -87,5 +88,5 @@ int main(int argc, char** argv)
cerr << "(nullController::main): catch ..." << endl; cerr << "(nullController::main): catch ..." << endl;
} }
return 0; return 1;
} }
...@@ -40,6 +40,7 @@ int main( int argc, const char **argv ) ...@@ -40,6 +40,7 @@ int main( int argc, const char **argv )
SystemMessage sm(SystemMessage::StartUp); SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() ); act.broadcast( sm.transport_msg() );
act.run(false); act.run(false);
return 0;
} }
catch( Exception& ex ) catch( Exception& ex )
{ {
...@@ -50,6 +51,6 @@ int main( int argc, const char **argv ) ...@@ -50,6 +51,6 @@ int main( int argc, const char **argv )
cout << "(main): Неизвестное исключение!!!!"<< endl; cout << "(main): Неизвестное исключение!!!!"<< endl;
} }
return 0; return 1;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
...@@ -46,6 +46,8 @@ int main(int argc, const char **argv) ...@@ -46,6 +46,8 @@ int main(int argc, const char **argv)
} }
else else
sv.view(); sv.view();
return 0;
} }
catch(Exception& ex ) catch(Exception& ex )
{ {
...@@ -56,5 +58,5 @@ int main(int argc, const char **argv) ...@@ -56,5 +58,5 @@ int main(int argc, const char **argv)
cerr << "(main): Неизвестное исключение!!!!"<< endl; 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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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-файла --> <!-- Генерирование cc-файла -->
<xsl:variable name="CLASSNAME"> <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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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-файла --> <!-- Генерирование cc-файла -->
<xsl:variable name="CLASSNAME"> <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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template> <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 ...@@ -387,7 +387,7 @@ void <xsl:value-of select="$CLASSNAME"/>_SK::setMsg( UniSetTypes::ObjectId _code
</xsl:when> </xsl:when>
<xsl:when test="normalize-space(@iotype)='DO'"> <xsl:when test="normalize-space(@iotype)='DO'">
<xsl:if test="normalize-space($onlymsg)=''"> <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> </xsl:if>
{ {
if( <xsl:value-of select="@name"/> != DefaultObjectId ) if( <xsl:value-of select="@name"/> != DefaultObjectId )
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template> <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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> 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:template name="settype">
<xsl:param name="iotype"/> <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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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:variable name="CLASSNAME">
<xsl:call-template name="settings-alone"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template> <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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template> <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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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:variable name="CLASSNAME">
<xsl:call-template name="settings-alone"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template> <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' <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'
xmlns:date="http://exslt.org/dates-and-times"> xmlns:date="http://exslt.org/dates-and-times">
<xsl:import href="ctl-cpp-common.xsl"/> <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:variable name="CLASSNAME">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template> <xsl:call-template name="settings"><xsl:with-param name="varname" select="'class-name'"/></xsl:call-template>
......
...@@ -17,7 +17,7 @@ print_usage() ...@@ -17,7 +17,7 @@ print_usage()
{ {
[ "$1" = 0 ] || exec >&2 [ "$1" = 0 ] || exec >&2
cat <<EOF cat <<EOF
Usage: ${0##*/} [options] programm Usage: ${0##*/} [options] programm [arguments]
Valid options are: Valid options are:
-h, --help display help screen -h, --help display help screen
...@@ -33,6 +33,9 @@ EOF ...@@ -33,6 +33,9 @@ EOF
[ -n "$1" ] && exit "$1" || exit [ -n "$1" ] && exit "$1" || exit
} }
[ -z "$1" ] && print_usage 1
#parse command line options #parse command line options
case "$1" in case "$1" in
-h|--help) print_usage 0;; -h|--help) print_usage 0;;
...@@ -54,13 +57,23 @@ then ...@@ -54,13 +57,23 @@ then
[ "$DBG" == "cache" ] && start_line="valgrind --tool=cachegrind --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" [ "$DBG" == "hel" ] && start_line="valgrind --tool=helgrind --trace-children=yes --log-file=valgrind.log $COMLINE"
PROG=`basename $1`
if [ "$DBG" == "gdb" ]; then 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 fi
echo Running "$start_line" echo Running "$start_line"
$start_line $start_line
exit 0 exit $?
fi fi
if [ -n "$FG" ] if [ -n "$FG" ]
...@@ -69,20 +82,19 @@ then ...@@ -69,20 +82,19 @@ then
if [ -z "$COMLINE" ] if [ -z "$COMLINE" ]
then then
echo "Не указана команда для запуска" echo "Не указана команда для запуска"
exit 0 exit 1
fi fi
COMLINE="$COMLINE --uniset-port $OMNIPORT" COMLINE="$COMLINE --uniset-port $OMNIPORT"
echo Запускаем "$COMLINE" echo Запускаем "$COMLINE"
$COMLINE $COMLINE
echo Выходим exit $?
exit 1
fi fi
if [ -z "$*" ] if [ -z "$*" ]
then then
echo "Не указана команда для запуска" echo "Не указана команда для запуска"
exit 0 exit 1
fi fi
checkPID=$(echo "$1" | grep pidfile=) checkPID=$(echo "$1" | grep pidfile=)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Name: libuniset Name: libuniset
Version: 1.0 Version: 1.0
Release: alt14 Release: alt31
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
License: GPL License: GPL
Group: Development/C++ Group: Development/C++
...@@ -43,6 +43,16 @@ Obsoletes: %oname-mysql-dbserver ...@@ -43,6 +43,16 @@ Obsoletes: %oname-mysql-dbserver
%description mysql-dbserver %description mysql-dbserver
MySQL dbserver for %name 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 %package utils
Summary: UniSet utilities Summary: UniSet utilities
Group: Development/Tools Group: Development/Tools
...@@ -54,7 +64,7 @@ Obsoletes: %oname-utils ...@@ -54,7 +64,7 @@ Obsoletes: %oname-utils
UniSet utilities UniSet utilities
%package doc %package doc
Group: Development/C Group: Development/C++
Summary: Documentations for developing with UniSet Summary: Documentations for developing with UniSet
Requires: lib%name = %version-%release Requires: lib%name = %version-%release
...@@ -62,7 +72,7 @@ Requires: lib%name = %version-%release ...@@ -62,7 +72,7 @@ Requires: lib%name = %version-%release
Documentations for developing with UniSet Documentations for developing with UniSet
%package extensions %package extensions
Group: Development/Databases Group: Development/C++
Summary: libUniSet extensions Summary: libUniSet extensions
Requires: %name = %version-%release Requires: %name = %version-%release
Provides: %oname-extentions Provides: %oname-extentions
...@@ -74,7 +84,7 @@ Obsoletes: %name-extentions ...@@ -74,7 +84,7 @@ Obsoletes: %name-extentions
Extensions for libuniset Extensions for libuniset
%package extensions-devel %package extensions-devel
Group: Development/Databases Group: Development/C++
Summary: Libraries needed to develop for uniset extensions Summary: Libraries needed to develop for uniset extensions
Requires: %name-extensions = %version-%release Requires: %name-extensions = %version-%release
Provides: %name-extentions-devel Provides: %name-extentions-devel
...@@ -135,6 +145,9 @@ rm -f %buildroot%_libdir/*.la ...@@ -135,6 +145,9 @@ rm -f %buildroot%_libdir/*.la
%_bindir/%oname-mysql-*dbserver %_bindir/%oname-mysql-*dbserver
%_libdir/*-mysql.so* %_libdir/*-mysql.so*
%files mysql-devel
%_pkgconfigdir/libUniSetMySQL.pc
%if_enabled doc %if_enabled doc
%files doc %files doc
%_docdir/%name %_docdir/%name
...@@ -186,11 +199,69 @@ rm -f %buildroot%_libdir/*.la ...@@ -186,11 +199,69 @@ rm -f %buildroot%_libdir/*.la
%_pkgconfigdir/libUniSetShared*.pc %_pkgconfigdir/libUniSetShared*.pc
%_pkgconfigdir/libUniSetNetwork*.pc %_pkgconfigdir/libUniSetNetwork*.pc
%_pkgconfigdir/libUniSetUNet*.pc %_pkgconfigdir/libUniSetUNet*.pc
#%_pkgconfigdir/libUniSetSMDBServer.pc #%_pkgconfigdir/libUniSetSMDBServer.pc
#%_pkgconfigdir/libUniSet*.pc #%_pkgconfigdir/libUniSet*.pc
%exclude %_pkgconfigdir/libUniSet.pc %exclude %_pkgconfigdir/libUniSet.pc
%changelog %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 * Thu Mar 24 2011 Pavel Vainerman <pv@altlinux.ru> 1.0-alt14
- fixed bug in MBSlave - fixed bug in MBSlave
......
...@@ -81,16 +81,16 @@ ...@@ -81,16 +81,16 @@
priority - приоритет сообщения об изменении данного датчика priority - приоритет сообщения об изменении данного датчика
textname - текстовое имя датчика textname - текстовое имя датчика
--> -->
<nodes port="2809"> <nodes port="2809" unet_broadcast_ip="192.168.1.255">
<item infserver="InfoServer" ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="1" unet_port="3000" unet_ip="192.168.56.255"> <item infserver="InfoServer" ip="127.0.0.1" name="LocalhostNode" textname="Локальный узел" unet_ignore="0" unet_port="2048">
<iocards> <iocards>
<item card="1" name="DI32"/> <item card="1" name="DI32"/>
<item card="2" name="DO32"/> <item card="2" name="DO32"/>
<item baddr="0x110" card="3" dev="/dev/comedi1" name="UNIO48" subdev1="TBI24_0" subdev2="TBI16_8"/> <item baddr="0x110" card="3" dev="/dev/comedi1" name="UNIO48" subdev1="TBI24_0" subdev2="TBI16_8"/>
</iocards> </iocards>
</item> </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.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"/> <item ip="192.168.56.11" name="Node2" textname="Node2" unet_port="3002" unet_ip="192.168.56.255" unet_ignore="1"/>
</nodes> </nodes>
<!-- ************************ Датчики ********************** --> <!-- ************************ Датчики ********************** -->
<sensors name="Sensors"> <sensors name="Sensors">
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# See doc: http://www.gnu.org/software/hello/manual/autoconf/Generic-Programs.html # See doc: http://www.gnu.org/software/hello/manual/autoconf/Generic-Programs.html
# AC_PREREQ(2.59) # 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) AM_INIT_AUTOMAKE(AC_PACKAGE_NAME,AC_PACKAGE_VERSION)
# AC_CONFIG_MACRO_DIR([m4]) # AC_CONFIG_MACRO_DIR([m4])
...@@ -30,7 +30,7 @@ AC_ENABLE_SHARED(yes) ...@@ -30,7 +30,7 @@ AC_ENABLE_SHARED(yes)
AC_ENABLE_STATIC(no) AC_ENABLE_STATIC(no)
AM_PROG_LIBTOOL AM_PROG_LIBTOOL
LIBVER=1:1:0 LIBVER=1:2:0
AC_SUBST(LIBVER) AC_SUBST(LIBVER)
# Checks for libraries. # Checks for libraries.
...@@ -167,7 +167,6 @@ AC_CONFIG_FILES([Makefile ...@@ -167,7 +167,6 @@ AC_CONFIG_FILES([Makefile
Utilities/SMonit/Makefile Utilities/SMonit/Makefile
Utilities/InfoServer/Makefile Utilities/InfoServer/Makefile
Utilities/MBTester/Makefile Utilities/MBTester/Makefile
Utilities/DBServer-MySQL/Makefile
Utilities/SImitator/Makefile Utilities/SImitator/Makefile
Utilities/codegen/Makefile Utilities/codegen/Makefile
Utilities/codegen/uniset-codegen Utilities/codegen/uniset-codegen
...@@ -176,14 +175,12 @@ AC_CONFIG_FILES([Makefile ...@@ -176,14 +175,12 @@ AC_CONFIG_FILES([Makefile
extensions/libUniSetExtensions.pc extensions/libUniSetExtensions.pc
extensions/lib/Makefile extensions/lib/Makefile
extensions/include/Makefile extensions/include/Makefile
extensions/DBServer-MySQL/Makefile
extensions/DBServer-MySQL/libUniSetMySQL.pc
extensions/IOControl/Makefile extensions/IOControl/Makefile
extensions/IOControl/libUniSetIOControl.pc extensions/IOControl/libUniSetIOControl.pc
extensions/RTUExchange/Makefile extensions/RTUExchange/Makefile
extensions/RTUExchange/libUniSetRTU.pc extensions/RTUExchange/libUniSetRTU.pc
extensions/UDPExchange/Makefile
extensions/UDPExchange/libUniSetUDP.pc
extensions/UNet2/Makefile
extensions/UNet2/libUniSetUNet2.pc
extensions/ModbusSlave/Makefile extensions/ModbusSlave/Makefile
extensions/ModbusSlave/libUniSetMBSlave.pc extensions/ModbusSlave/libUniSetMBSlave.pc
extensions/MBTCPMaster/Makefile extensions/MBTCPMaster/Makefile
...@@ -193,6 +190,8 @@ AC_CONFIG_FILES([Makefile ...@@ -193,6 +190,8 @@ AC_CONFIG_FILES([Makefile
extensions/SMViewer/Makefile extensions/SMViewer/Makefile
extensions/UniNetwork/Makefile extensions/UniNetwork/Makefile
extensions/UniNetwork/libUniSetNetwork.pc extensions/UniNetwork/libUniSetNetwork.pc
extensions/UNet2/Makefile
extensions/UNet2/libUniSetUNet2.pc
extensions/SharedMemory/Makefile extensions/SharedMemory/Makefile
extensions/SharedMemory/libUniSetSharedMemory.pc extensions/SharedMemory/libUniSetSharedMemory.pc
extensions/SharedMemoryPlus/Makefile]) extensions/SharedMemoryPlus/Makefile])
......
if DISABLE_MYSQL
else
UMYSQL_VER=@LIBVER@ UMYSQL_VER=@LIBVER@
lib_LTLIBRARIES = libUniSet-mysql.la lib_LTLIBRARIES = libUniSet-mysql.la
...@@ -14,3 +18,8 @@ include $(top_builddir)/conf/setting.mk ...@@ -14,3 +18,8 @@ include $(top_builddir)/conf/setting.mk
# install # install
devel_include_HEADERS = *.h devel_include_HEADERS = *.h
devel_includedir = $(includedir)/@PACKAGE@/mysql 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[]) ...@@ -147,7 +147,7 @@ int main(int argc, char* argv[])
case '?': case '?':
default: default:
printf("? argument\n"); printf("? argument\n");
return 0; return 1;
} }
} }
...@@ -419,7 +419,6 @@ void openXML() ...@@ -419,7 +419,6 @@ void openXML()
} }
uxml.close(); uxml.close();
return;
} }
catch( ... ) catch( ... )
{ {
......
...@@ -65,6 +65,7 @@ int main(int argc, const char **argv) ...@@ -65,6 +65,7 @@ int main(int argc, const char **argv)
act.run(true); act.run(true);
msleep(500); msleep(500);
ic->execute(); ic->execute();
return 0;
} }
catch(SystemError& err) catch(SystemError& err)
{ {
...@@ -79,5 +80,5 @@ int main(int argc, const char **argv) ...@@ -79,5 +80,5 @@ int main(int argc, const char **argv)
dlog[Debug::CRIT] << "(iocontrol): catch(...)" << endl; dlog[Debug::CRIT] << "(iocontrol): catch(...)" << endl;
} }
return 0; return 1;
} }
#ifndef LProcessor_H_ #ifndef LProcessor_H_
#define 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 <map>
#include "UniSetTypes.h" #include "UniSetTypes.h"
#include "UniversalInterface.h" #include "UniversalInterface.h"
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "SMInterface.h" #include "SMInterface.h"
#include "LProcessor.h" #include "LProcessor.h"
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
/*! Реализация LogicProccessor основанная на заказе датчиков */
class PassiveLProcessor: class PassiveLProcessor:
public UniSetObject_LT, public UniSetObject_LT,
protected LProcessor protected LProcessor
......
...@@ -35,6 +35,7 @@ int main(int argc, const char **argv) ...@@ -35,6 +35,7 @@ int main(int argc, const char **argv)
LProcessor plc; LProcessor plc;
plc.execute(schema); plc.execute(schema);
return 0;
} }
catch( LogicException& ex ) catch( LogicException& ex )
{ {
...@@ -49,6 +50,6 @@ int main(int argc, const char **argv) ...@@ -49,6 +50,6 @@ int main(int argc, const char **argv)
cerr << " catch ... " << endl; cerr << " catch ... " << endl;
} }
return 0; return 1;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -81,7 +81,7 @@ int main(int argc, const char **argv) ...@@ -81,7 +81,7 @@ int main(int argc, const char **argv)
dlog(Debug::ANY) << "\n\n\n"; dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- IOControl START -------------------------\n\n"; dlog[Debug::ANY] << "(main): -------------- IOControl START -------------------------\n\n";
act.run(false); act.run(false);
pause(); return 0;
} }
catch( LogicException& ex ) catch( LogicException& ex )
{ {
...@@ -96,6 +96,6 @@ int main(int argc, const char **argv) ...@@ -96,6 +96,6 @@ int main(int argc, const char **argv)
cerr << " catch ... " << endl; cerr << " catch ... " << endl;
} }
return 0; return 1;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -80,6 +80,9 @@ pollThread(0) ...@@ -80,6 +80,9 @@ pollThread(0)
initPause = conf->getArgPInt("--" + prefix + "-initPause",it.getProp("initPause"), 3000); 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 = conf->getArgInt("--" + prefix + "-force",it.getProp("force"));
force_out = conf->getArgInt("--" + prefix + "-force-out",it.getProp("force_out")); force_out = conf->getArgInt("--" + prefix + "-force-out",it.getProp("force_out"));
...@@ -182,6 +185,8 @@ void MBTCPMaster::initMB( bool reopen ) ...@@ -182,6 +185,8 @@ void MBTCPMaster::initMB( bool reopen )
if( recv_timeout > 0 ) if( recv_timeout > 0 )
mb->setTimeout(recv_timeout); mb->setTimeout(recv_timeout);
mb->setSleepPause(sleepPause_usec);
dlog[Debug::INFO] << myname << "(init): ipaddr=" << iaddr << " port=" << port << endl; dlog[Debug::INFO] << myname << "(init): ipaddr=" << iaddr << " port=" << port << endl;
if( dlog.debugging(Debug::LEVEL9) ) if( dlog.debugging(Debug::LEVEL9) )
......
...@@ -420,6 +420,7 @@ class MBTCPMaster: ...@@ -420,6 +420,7 @@ class MBTCPMaster:
bool force_out; /*!< флаг означающий, принудительного чтения выходов */ bool force_out; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID; bool mbregFromID;
int polltime; /*!< переодичность обновления данных, [мсек] */ int polltime; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_usec;
PassiveTimer ptHeartBeat; PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat; UniSetTypes::ObjectId sidHeartBeat;
......
#include <sys/wait.h>
#include <sstream> #include <sstream>
#include "MBTCPMaster.h" #include "MBTCPMaster.h"
#include "Configuration.h" #include "Configuration.h"
...@@ -69,6 +70,8 @@ int main( int argc, const char** argv ) ...@@ -69,6 +70,8 @@ int main( int argc, const char** argv )
dlog(Debug::ANY) << "\n\n\n"; dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- MBTCP Exchange START -------------------------\n\n"; dlog[Debug::ANY] << "(main): -------------- MBTCP Exchange START -------------------------\n\n";
act.run(false); act.run(false);
while( waitpid(-1, 0, 0) > 0 );
return 0;
} }
catch( Exception& ex ) catch( Exception& ex )
{ {
...@@ -79,5 +82,6 @@ int main( int argc, const char** argv ) ...@@ -79,5 +82,6 @@ int main( int argc, const char** argv )
dlog[Debug::CRIT] << "(mbtcpmaster): catch ..." << std::endl; dlog[Debug::CRIT] << "(mbtcpmaster): catch ..." << std::endl;
} }
return 0; while( waitpid(-1, 0, 0) > 0 );
return 1;
} }
#!/bin/sh #!/bin/sh
uniset-start.sh -f ./uniset-mbtcpmaster \ ./uniset-start.sh -g ./uniset-mbtcpmaster \
--confile test.xml \ --confile test.xml \
--mbtcp-name MBMaster1 \ --mbtcp-name MBMaster1 \
--smemory-id SharedMemory \ --smemory-id SharedMemory \
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
if HAVE_EXTENTIONS if HAVE_EXTENTIONS
SUBDIRS = lib include SharedMemory IOControl RTUExchange LogicProcessor \ SUBDIRS = lib include SharedMemory IOControl RTUExchange LogicProcessor \
ModbusSlave MBTCPMaster SMViewer UniNetwork UNet2 ModbusSlave MBTCPMaster SMViewer UniNetwork UNet2 DBServer-MySQL
#SMDBServer #SMDBServer
#SharedMemoryPlus #SharedMemoryPlus
#UDPExchange #UDPExchange
......
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#include <sys/wait.h>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <cc++/socket.h> #include <cc++/socket.h>
...@@ -74,7 +75,8 @@ int main(int argc, const char **argv) ...@@ -74,7 +75,8 @@ int main(int argc, const char **argv)
dlog[Debug::ANY] << "(main): -------------- MBSlave START -------------------------\n\n"; dlog[Debug::ANY] << "(main): -------------- MBSlave START -------------------------\n\n";
act.run(false); act.run(false);
while( waitpid(-1, 0, 0) > 0 );
return 0;
} }
catch( SystemError& err ) catch( SystemError& err )
{ {
...@@ -84,15 +86,16 @@ int main(int argc, const char **argv) ...@@ -84,15 +86,16 @@ int main(int argc, const char **argv)
{ {
dlog[Debug::CRIT] << "(mbslave): " << ex << endl; 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(...) catch(...)
{ {
dlog[Debug::CRIT] << "(mbslave): catch(...)" << endl; dlog[Debug::CRIT] << "(mbslave): catch(...)" << endl;
} }
return 0; while( waitpid(-1, 0, 0) > 0 );
return 1;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -62,9 +62,10 @@ prefix(prefix_) ...@@ -62,9 +62,10 @@ prefix(prefix_)
recv_timeout = conf->getArgPInt("--"+prefix+"-recv-timeout",it.getProp("recv_timeout"), 50); recv_timeout = conf->getArgPInt("--"+prefix+"-recv-timeout",it.getProp("recv_timeout"), 50);
int alltout = conf->getArgPInt("--"+prefix+"-all-timeout",it.getProp("all_timeout"), 2000); int alltout = conf->getArgPInt("--"+prefix+"-all-timeout",it.getProp("all_timeout"), 2000);
ptAllNotRespond.setTiming(alltout); 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")); rs_pre_clean = conf->getArgInt("--"+prefix+"-pre-clean",it.getProp("pre_clean"));
noQueryOptimization = conf->getArgInt("--"+prefix+"-no-query-optimization",it.getProp("no_query_optimization")); noQueryOptimization = conf->getArgInt("--"+prefix+"-no-query-optimization",it.getProp("no_query_optimization"));
...@@ -185,6 +186,8 @@ void RTUExchange::initMB( bool reopen ) ...@@ -185,6 +186,8 @@ void RTUExchange::initMB( bool reopen )
if( recv_timeout > 0 ) if( recv_timeout > 0 )
mb->setTimeout(recv_timeout); mb->setTimeout(recv_timeout);
mb->setSleepPause(sleepPause_usec);
dlog[Debug::INFO] << myname << "(init): dev=" << devname << " speed=" << ComPort::getSpeed(defSpeed) << endl; dlog[Debug::INFO] << myname << "(init): dev=" << devname << " speed=" << ComPort::getSpeed(defSpeed) << endl;
} }
catch(...) catch(...)
...@@ -937,29 +940,6 @@ void RTUExchange::sigterm( int signo ) ...@@ -937,29 +940,6 @@ void RTUExchange::sigterm( int signo )
{ {
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl; cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false; 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); UniSetObject_LT::sigterm(signo);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
......
...@@ -244,6 +244,7 @@ class RTUExchange: ...@@ -244,6 +244,7 @@ class RTUExchange:
bool force_out; /*!< флаг означающий, принудительного чтения выходов */ bool force_out; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID; bool mbregFromID;
int polltime; /*!< переодичность обновления данных, [мсек] */ int polltime; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_usec;
PassiveTimer ptHeartBeat; PassiveTimer ptHeartBeat;
UniSetTypes::ObjectId sidHeartBeat; UniSetTypes::ObjectId sidHeartBeat;
......
...@@ -363,6 +363,7 @@ int main( int argc, char **argv ) ...@@ -363,6 +363,7 @@ int main( int argc, char **argv )
return 1; return 1;
} }
return 0;
} }
catch( ModbusRTU::mbException& ex ) catch( ModbusRTU::mbException& ex )
{ {
...@@ -381,7 +382,7 @@ int main( int argc, char **argv ) ...@@ -381,7 +382,7 @@ int main( int argc, char **argv )
cerr << "(mtr-setup): catch(...)" << endl; cerr << "(mtr-setup): catch(...)" << endl;
} }
return 0; return 1;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
char* checkArg( int i, int argc, char* argv[] ) char* checkArg( int i, int argc, char* argv[] )
......
...@@ -120,6 +120,7 @@ int main( int argc, const char **argv ) ...@@ -120,6 +120,7 @@ int main( int argc, const char **argv )
else else
{ {
cout << " Unknown type: " << type << endl; cout << " Unknown type: " << type << endl;
return 1;
} }
return 0; return 0;
......
#include <sys/wait.h>
#include <sstream> #include <sstream>
#include "ObjectsActivator.h" #include "ObjectsActivator.h"
#include "Extensions.h" #include "Extensions.h"
...@@ -68,8 +69,9 @@ int main( int argc, char** argv ) ...@@ -68,8 +69,9 @@ int main( int argc, char** argv )
dlog[Debug::ANY] << "(main): -------------- RTU Exchange START -------------------------\n\n"; dlog[Debug::ANY] << "(main): -------------- RTU Exchange START -------------------------\n\n";
act.run(false); act.run(false);
// msleep(500);
// rs->execute(); while( waitpid(-1, 0, 0) > 0 );
return 0;
} }
catch( Exception& ex ) catch( Exception& ex )
{ {
...@@ -80,5 +82,6 @@ int main( int argc, char** argv ) ...@@ -80,5 +82,6 @@ int main( int argc, char** argv )
dlog[Debug::CRIT] << "(rtuexchange): catch ..." << std::endl; 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 ) ...@@ -108,6 +108,8 @@ int main( int argc, char **argv )
cout << "UNIO1 AI" << i << ": " << rtu.getFloat( RTUStorage::nJ1, i, UniversalIO::AnalogInput ) << endl; cout << "UNIO1 AI" << i << ": " << rtu.getFloat( RTUStorage::nJ1, i, UniversalIO::AnalogInput ) << endl;
for( int i=0; i<24; i++ ) for( int i=0; i<24; i++ )
cout << "UNIO1 DI" << i << ": " << rtu.getState( RTUStorage::nJ1, i, UniversalIO::DigitalInput ) << endl; cout << "UNIO1 DI" << i << ": " << rtu.getState( RTUStorage::nJ1, i, UniversalIO::DigitalInput ) << endl;
return 0;
} }
catch( ModbusRTU::mbException& ex ) catch( ModbusRTU::mbException& ex )
{ {
...@@ -126,6 +128,6 @@ int main( int argc, char **argv ) ...@@ -126,6 +128,6 @@ int main( int argc, char **argv )
cerr << "(rtustate): catch(...)" << endl; cerr << "(rtustate): catch(...)" << endl;
} }
return 0; return 1;
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
...@@ -69,6 +69,7 @@ int main( int argc, const char** argv ) ...@@ -69,6 +69,7 @@ int main( int argc, const char** argv )
dlog(Debug::ANY) << "\n\n\n"; dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- SMDBServer START -------------------------\n\n"; dlog[Debug::ANY] << "(main): -------------- SMDBServer START -------------------------\n\n";
act.run(false); act.run(false);
return 0;
} }
catch( Exception& ex ) catch( Exception& ex )
{ {
...@@ -79,5 +80,5 @@ int main( int argc, const char** argv ) ...@@ -79,5 +80,5 @@ int main( int argc, const char** argv )
dlog[Debug::CRIT] << "(smdbserver): catch ..." << std::endl; dlog[Debug::CRIT] << "(smdbserver): catch ..." << std::endl;
} }
return 0; return 1;
} }
...@@ -36,6 +36,7 @@ int main( int argc, const char **argv ) ...@@ -36,6 +36,7 @@ int main( int argc, const char **argv )
SMViewer smv(shmID); SMViewer smv(shmID);
smv.run(); smv.run();
return 0;
} }
catch( Exception& ex ) catch( Exception& ex )
{ {
...@@ -46,6 +47,6 @@ int main( int argc, const char **argv ) ...@@ -46,6 +47,6 @@ int main( int argc, const char **argv )
cout << "Неизвестное исключение!!!!"<< endl; cout << "Неизвестное исключение!!!!"<< endl;
} }
return 0; return 1;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
...@@ -42,14 +42,18 @@ int main(int argc, const char **argv) ...@@ -42,14 +42,18 @@ int main(int argc, const char **argv)
// pause(); // пауза, чтобы дочерние потоки успели завершить работу // pause(); // пауза, чтобы дочерние потоки успели завершить работу
return 0; return 0;
} }
catch(SystemError& err) catch( SystemError& err )
{ {
unideb[Debug::CRIT] << "(smemory): " << err << endl; unideb[Debug::CRIT] << "(smemory): " << err << endl;
} }
catch(Exception& ex) catch( Exception& ex )
{ {
unideb[Debug::CRIT] << "(smemory): " << ex << endl; unideb[Debug::CRIT] << "(smemory): " << ex << endl;
} }
catch( std::exception& e )
{
unideb[Debug::CRIT] << "(smemory): " << e.what() << endl;
}
catch(...) catch(...)
{ {
unideb[Debug::CRIT] << "(smemory): catch(...)" << endl; 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
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UDPExchange.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UDPExchange::UDPExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic ):
UniSetObject_LT(objId),
shm(0),
initPause(0),
udp(0),
activated(false),
dlist(100),
maxItem(0)
{
if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(UDPExchange): objId=-1?!! Use --udp-name" );
// xmlNode* cnode = conf->getNode(myname);
cnode = conf->getNode(myname);
if( cnode == NULL )
throw UniSetTypes::SystemError("(UDPExchange): Not find conf-node for " + myname );
shm = new SMInterface(shmId,&ui,objId,ic);
UniXML_iterator it(cnode);
// определяем фильтр
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;
// ---------- init RS ----------
// UniXML_iterator it(cnode);
s_host = conf->getArgParam("--udp-host",it.getProp("host"));
if( s_host.empty() )
throw UniSetTypes::SystemError(myname+"(UDPExchange): Unknown host. Use --udp-host" );
host = s_host.c_str();
buildReceiverList();
// port = conf->getArgInt("--udp-port",it.getProp("port"));
if( port <= 0 || port == DefaultObjectId )
throw UniSetTypes::SystemError(myname+"(UDPExchange): Unknown port address" );
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UDPExchange): UDP set to " << s_host << ":" << port << endl;
try
{
udp = new ost::UDPBroadcast(host,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString() << endl;
throw SystemError(s.str());
}
thr = new ThreadCreator<UDPExchange>(this, &UDPExchange::poll);
recvTimeout = conf->getArgPInt("--udp-recv-timeout",it.getProp("recvTimeout"), 5000);
sendTimeout = conf->getArgPInt("--udp-send-timeout",it.getProp("sendTimeout"), 5000);
polltime = conf->getArgPInt("--udp-polltime",it.getProp("polltime"), 100);
// -------------------------------
if( shm->isLocalwork() )
{
readConfiguration();
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
}
else
ic->addReadItem( sigc::mem_fun(this,&UDPExchange::readItem) );
// ********** HEARTBEAT *************
string heart = conf->getArgParam("--udp-heartbeat-id",it.getProp("heartbeat_id"));
if( !heart.empty() )
{
sidHeartBeat = conf->getSensorID(heart);
if( sidHeartBeat == DefaultObjectId )
{
ostringstream err;
err << myname << ": не найден идентификатор для датчика 'HeartBeat' " << heart;
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
int heartbeatTime = getHeartBeatTime();
if( heartbeatTime )
ptHeartBeat.setTiming(heartbeatTime);
else
ptHeartBeat.setTiming(UniSetTimer::WaitUpTime);
maxHeartBeat = conf->getArgPInt("--udp-heartbeat-max", it.getProp("heartbeat_max"), 10);
test_id = sidHeartBeat;
}
else
{
test_id = conf->getSensorID("TestMode_S");
if( test_id == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): test_id unknown. 'TestMode_S' not found...";
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl;
activateTimeout = conf->getArgPInt("--activate-timeout", 20000);
timeout_t msec = conf->getArgPInt("--udp-timeout",it.getProp("timeout"), 3000);
dlog[Debug::INFO] << myname << "(init): udp-timeout=" << msec << " msec" << endl;
}
// -----------------------------------------------------------------------------
UDPExchange::~UDPExchange()
{
for( ReceiverList::iterator it=rlist.begin(); it!=rlist.end(); it++ )
delete (*it);
delete udp;
delete shm;
delete thr;
}
// -----------------------------------------------------------------------------
void UDPExchange::waitSMReady()
{
// waiting for SM is ready...
int ready_timeout = conf->getArgInt("--udp-sm-ready-timeout","15000");
if( ready_timeout == 0 )
ready_timeout = 15000;
else if( ready_timeout < 0 )
ready_timeout = UniSetTimer::WaitUpTime;
if( !shm->waitSMready(ready_timeout,50) )
{
ostringstream err;
err << myname << "(waitSMReady): Не дождались готовности SharedMemory к работе в течение " << ready_timeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
throw SystemError(err.str());
}
}
// -----------------------------------------------------------------------------
void UDPExchange::step()
{
if( !activated )
return;
if( sidHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
shm->localSaveValue(aitHeartBeat,sidHeartBeat,maxHeartBeat,getId());
ptHeartBeat.reset();
}
catch(Exception& ex)
{
dlog[Debug::CRIT] << myname
<< "(step): (hb) " << ex << std::endl;
}
}
}
// -----------------------------------------------------------------------------
void UDPExchange::poll()
{
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
for( ReceiverList::iterator it=rlist.begin(); it!=rlist.end(); it++ )
{
(*it)->setReceiveTimeout(recvTimeout);
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(poll): start exchange for " << (*it)->getName() << endl;
(*it)->start();
}
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
{
send();
}
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;
}
msleep(polltime);
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UDPExchange::send()
{
cout << myname << ": send..." << endl;
/*
UniSetUDP::UDPHeader h;
h.nodeID = conf->getLocalNode();
h.procID = getId();
h.dcount = mypack.size();
if( udp->isPending(ost::Socket::pendingOutput) )
{
size_t ret = udp->send((char*)(&h),sizeof(h));
if( ret<(size_t)sizeof(h) )
{
cerr << myname << "(send data header): ret=" << ret << " sizeof=" << sizeof(h) << endl;
return;
}
*/
/*! \todo Подумать нужен ли здесь mutex */
UniSetUDP::UDPMessage::UDPDataList::iterator it = mypack.dlist.begin();
for( ; it!=mypack.dlist.end(); ++it )
{
// while( !udp->isPending(ost::Socket::pendingOutput) )
// msleep(30);
cout << myname << "(send): " << (*it) << endl;
size_t ret = udp->send((char*)(&(*it)),sizeof(UniSetUDP::UDPData));
if( ret<(size_t)sizeof(UniSetUDP::UDPData) )
{
cerr << myname << "(send data): ret=" << ret << " sizeof=" << sizeof(UniSetUDP::UDPData) << endl;
break;
}
}
// }
}
// -----------------------------------------------------------------------------
void UDPExchange::processingMessage(UniSetTypes::VoidMessage *msg)
{
try
{
switch(msg->type)
{
case UniSetTypes::Message::SysCommand:
{
UniSetTypes::SystemMessage sm( msg );
sysCommand( &sm );
}
break;
case Message::SensorInfo:
{
SensorMessage sm( msg );
sensorInfo(&sm);
}
break;
default:
break;
}
}
catch( SystemError& ex )
{
dlog[Debug::CRIT] << myname << "(SystemError): " << ex << std::endl;
// throw SystemError(ex);
raise(SIGTERM);
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << myname << "(processingMessage): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(processingMessage): catch ...\n";
}
}
// -----------------------------------------------------------------------------
void UDPExchange::sysCommand(UniSetTypes::SystemMessage *sm)
{
switch( sm->command )
{
case SystemMessage::StartUp:
{
waitSMReady();
// подождать пока пройдёт инициализация датчиков
// см. activateObject()
msleep(initPause);
PassiveTimer ptAct(activateTimeout);
while( !activated && !ptAct.checkTime() )
{
cout << myname << "(sysCommand): wait activate..." << endl;
msleep(300);
if( activated )
break;
}
if( !activated )
dlog[Debug::CRIT] << myname << "(sysCommand): ************* don`t activate?! ************" << endl;
{
UniSetTypes::uniset_mutex_lock l(mutex_start, 10000);
askSensors(UniversalIO::UIONotify);
}
thr->start();
}
case SystemMessage::FoldUp:
case SystemMessage::Finish:
askSensors(UniversalIO::UIODontNotify);
break;
case SystemMessage::WatchDog:
{
// ОПТИМИЗАЦИЯ (защита от двойного перезаказа при старте)
// Если идёт локальная работа
// (т.е. UDPExchange запущен в одном процессе с SharedMemory2)
// то обрабатывать WatchDog не надо, т.к. мы и так ждём готовности SM
// при заказе датчиков, а если SM вылетит, то вместе с этим процессом(UDPExchange)
if( shm->isLocalwork() )
break;
askSensors(UniversalIO::UIONotify);
}
break;
case SystemMessage::LogRotate:
{
// переоткрываем логи
unideb << myname << "(sysCommand): logRotate" << std::endl;
string fname = unideb.getLogFile();
if( !fname.empty() )
{
unideb.logFile(fname);
unideb << myname << "(sysCommand): ***************** UNIDEB LOG ROTATE *****************" << std::endl;
}
dlog << myname << "(sysCommand): logRotate" << std::endl;
fname = dlog.getLogFile();
if( !fname.empty() )
{
dlog.logFile(fname);
dlog << myname << "(sysCommand): ***************** dlog LOG ROTATE *****************" << std::endl;
}
}
break;
default:
break;
}
}
// ------------------------------------------------------------------------------------------
void UDPExchange::askSensors( UniversalIO::UIOCommand cmd )
{
if( !shm->waitSMworking(test_id,activateTimeout,50) )
{
ostringstream err;
err << myname
<< "(askSensors): Не дождались готовности(work) SharedMemory к работе в течение "
<< activateTimeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
kill(SIGTERM,getpid()); // прерываем (перезапускаем) процесс...
throw SystemError(err.str());
}
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
try
{
shm->askSensor(it->si.id,cmd);
}
catch( UniSetTypes::Exception& ex )
{
dlog[Debug::WARN] << myname << "(askSensors): " << ex << std::endl;
}
catch(...){}
}
}
// ------------------------------------------------------------------------------------------
void UDPExchange::sensorInfo( UniSetTypes::SensorMessage* sm )
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
if( it->si.id == sm->id )
{
uniset_spin_lock lock(it->val_lock);
it->val = sm->value;
if( it->pack_it != mypack.dlist.end() )
it->pack_it->val = sm->value;
}
break;
}
}
// ------------------------------------------------------------------------------------------
bool UDPExchange::activateObject()
{
// блокирование обработки Starsp
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated = false;
UniSetTypes::uniset_mutex_lock l(mutex_start, 5000);
UniSetObject_LT::activateObject();
initIterators();
activated = true;
}
return true;
}
// ------------------------------------------------------------------------------------------
void UDPExchange::sigterm( int signo )
{
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false;
udp->disconnect();
for( ReceiverList::iterator it=rlist.begin(); it!=rlist.end(); it++ )
(*it)->stop();
UniSetObject_LT::sigterm(signo);
}
// ------------------------------------------------------------------------------------------
void UDPExchange::readConfiguration()
{
// readconf_ok = false;
xmlNode* root = conf->getXMLSensorsSection();
if(!root)
{
ostringstream err;
err << myname << "(readConfiguration): не нашли корневого раздела <sensors>";
throw SystemError(err.str());
}
UniXML_iterator it(root);
if( !it.goChildren() )
{
std::cerr << myname << "(readConfiguration): раздел <sensors> не содержит секций ?!!\n";
return;
}
for( ;it.getCurrent(); it.goNext() )
{
if( check_item(it) )
initItem(it);
}
// readconf_ok = true;
}
// ------------------------------------------------------------------------------------------
bool UDPExchange::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 UDPExchange::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
{
if( check_item(it) )
initItem(it);
return true;
}
// ------------------------------------------------------------------------------------------
bool UDPExchange::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_it = (mypack.dlist.end()--);
if( maxItem >= dlist.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 UDPExchange::initIterators()
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); it++ )
{
shm->initDIterator(it->dit);
shm->initAIterator(it->ait);
}
shm->initAIterator(aitHeartBeat);
}
// -----------------------------------------------------------------------------
void UDPExchange::help_print( int argc, char* argv[] )
{
cout << "--udp-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек." << endl;
cout << "--udp-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl;
cout << "--udp-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--udp-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--udp-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl;
cout << "--udp-notRespondSensor - датчик связи для данного процесса " << endl;
cout << "--udp-sm-ready-timeout - время на ожидание старта SM" << endl;
cout << " Настройки протокола UDP: " << endl;
cout << "--udp-host [ip|hostname] - Адрес сервера" << endl;
cout << "--udp-send-timeout - Таймаут на посылку ответа." << endl;
}
// -----------------------------------------------------------------------------
UDPExchange* UDPExchange::init_udpexchange( int argc, char* argv[], UniSetTypes::ObjectId icID, SharedMemory* ic )
{
string name = conf->getArgParam("--udp-name","UDPExchange1");
if( name.empty() )
{
cerr << "(udpexchange): Не задан name'" << endl;
return 0;
}
ObjectId ID = conf->getObjectID(name);
if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(udpexchange): идентификатор '" << name
<< "' не найден в конф. файле!"
<< " в секции " << conf->getObjectsSection() << endl;
return 0;
}
dlog[Debug::INFO] << "(rsexchange): name = " << name << "(" << ID << ")" << endl;
return new UDPExchange(ID,icID,ic);
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, UDPExchange::UItem& p )
{
return os << " sid=" << p.si.id;
}
// -----------------------------------------------------------------------------
void UDPExchange::buildReceiverList()
{
xmlNode* n = conf->getXMLNodesSection();
if( !n )
{
dlog[Debug::WARN] << myname << "(buildReceiverList): <nodes> not found! ignore..." << endl;
return;
}
UniXML_iterator it(n);
if( !it.goChildren() )
{
dlog[Debug::WARN] << myname << "(buildReceiverList): <nodes> is empty?! ignore..." << endl;
return;
}
for( ; it.getCurrent(); it.goNext() )
{
ObjectId n_id = conf->getNodeID( it.getProp("name") );
if( n_id == conf->getLocalNode() )
{
port = it.getIntProp("udp_port");
if( port<=0 )
port = n_id;
dlog[Debug::INFO] << myname << "(buildReceiverList): init myport port=" << port << endl;
continue;
}
int p = it.getIntProp("udp_port");
if( p <=0 )
p = n_id;
if( p == DefaultObjectId )
{
dlog[Debug::WARN] << myname << "(buildReceiverList): node=" << it.getProp("name") << " unknown port. ignore..." << endl;
continue;
}
UDPNReceiver* r = new UDPNReceiver(p,host,shm->getSMID(),shm->SM());
rlist.push_back(r);
}
}
// ------------------------------------------------------------------------------------------
#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_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UDPReceiver.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UDPReceiver::UDPReceiver( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic ):
UniSetObject_LT(objId),
shm(0),
initPause(0),
udp(0),
activated(false)
{
if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(UDPReceiver): objId=-1?!! Use --udp-name" );
// xmlNode* cnode = conf->getNode(myname);
cnode = conf->getNode(myname);
if( cnode == NULL )
throw UniSetTypes::SystemError("(UDPReceiver): Not find conf-node for " + myname );
shm = new SMInterface(shmId,&ui,objId,ic);
UniXML_iterator it(cnode);
// определяем фильтр
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;
// ---------- init RS ----------
// UniXML_iterator it(cnode);
string s_host = conf->getArgParam("--udp-host",it.getProp("host"));
if( s_host.empty() )
throw UniSetTypes::SystemError(myname+"(UDPReceiver): Unknown host. Use --udp-host" );
port = conf->getArgInt("--udp-port",it.getProp("port"));
if( port <= 0 )
throw UniSetTypes::SystemError(myname+"(UDPReceiver): Unknown port address. Use --udp-port" );
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UDPReceiver): UDP set to " << s_host << ":" << port << endl;
host = s_host.c_str();
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<UDPReceiver>(this, &UDPReceiver::poll);
recvTimeout = conf->getArgPInt("--udp-recv-timeout",it.getProp("recvTimeout"), 5000);
polltime = conf->getArgPInt("--udp-polltime",it.getProp("polltime"), 100);
// -------------------------------
// ********** HEARTBEAT *************
string heart = conf->getArgParam("--udp-heartbeat-id",it.getProp("heartbeat_id"));
if( !heart.empty() )
{
sidHeartBeat = conf->getSensorID(heart);
if( sidHeartBeat == DefaultObjectId )
{
ostringstream err;
err << myname << ": не найден идентификатор для датчика 'HeartBeat' " << heart;
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
int heartbeatTime = getHeartBeatTime();
if( heartbeatTime )
ptHeartBeat.setTiming(heartbeatTime);
else
ptHeartBeat.setTiming(UniSetTimer::WaitUpTime);
maxHeartBeat = conf->getArgPInt("--udp-heartbeat-max", it.getProp("heartbeat_max"), 10);
test_id = sidHeartBeat;
}
else
{
test_id = conf->getSensorID("TestMode_S");
if( test_id == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): test_id unknown. 'TestMode_S' not found...";
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl;
activateTimeout = conf->getArgPInt("--activate-timeout", 20000);
timeout_t msec = conf->getArgPInt("--udp-timeout",it.getProp("timeout"), 3000);
dlog[Debug::INFO] << myname << "(init): udp-timeout=" << msec << " msec" << endl;
}
// -----------------------------------------------------------------------------
UDPReceiver::~UDPReceiver()
{
delete udp;
delete shm;
delete thr;
}
// -----------------------------------------------------------------------------
void UDPReceiver::waitSMReady()
{
// waiting for SM is ready...
int ready_timeout = conf->getArgInt("--udp-sm-ready-timeout","15000");
if( ready_timeout == 0 )
ready_timeout = 15000;
else if( ready_timeout < 0 )
ready_timeout = UniSetTimer::WaitUpTime;
if( !shm->waitSMready(ready_timeout,50) )
{
ostringstream err;
err << myname << "(waitSMReady): Не дождались готовности SharedMemory к работе в течение " << ready_timeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
throw SystemError(err.str());
}
}
// -----------------------------------------------------------------------------
/*
void UDPReceiver::timerInfo( TimerMessage *tm )
{
if( tm->id == tmExchange )
step();
}
*/
// -----------------------------------------------------------------------------
void UDPReceiver::step()
{
// {
// uniset_mutex_lock l(pollMutex,2000);
// poll();
// }
if( !activated )
return;
if( sidHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
shm->localSaveValue(aitHeartBeat,sidHeartBeat,maxHeartBeat,getId());
ptHeartBeat.reset();
}
catch(Exception& ex)
{
dlog[Debug::CRIT] << myname
<< "(step): (hb) " << ex << std::endl;
}
}
}
// -----------------------------------------------------------------------------
void UDPReceiver::poll()
{
try
{
// udp->connect(host,port);
// udp->UDPSocket::setPeer(host,port);
}
catch( UniSetTypes::Exception& ex)
{
cerr << myname << "(step): " << ex << std::endl;
// reise(SIGTERM);
return;
}
while( activated )
{
try
{
recv();
// send();
}
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;
}
msleep(polltime);
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UDPReceiver::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 < 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 < sizeof(d) )
return;
}
return;
}
#endif
for( int i=0; i<h.dcount;i++ )
{
size_t ret = udp->UDPReceive::receive(&d,sizeof(d));
if( ret < 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;
// }
}
// -----------------------------------------------------------------------------
void UDPReceiver::processingMessage(UniSetTypes::VoidMessage *msg)
{
try
{
switch(msg->type)
{
case UniSetTypes::Message::SysCommand:
{
UniSetTypes::SystemMessage sm( msg );
sysCommand( &sm );
}
break;
case Message::SensorInfo:
{
SensorMessage sm( msg );
sensorInfo(&sm);
}
break;
default:
break;
}
}
catch( SystemError& ex )
{
dlog[Debug::CRIT] << myname << "(SystemError): " << ex << std::endl;
// throw SystemError(ex);
raise(SIGTERM);
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << myname << "(processingMessage): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(processingMessage): catch ...\n";
}
}
// -----------------------------------------------------------------------------
void UDPReceiver::sysCommand(UniSetTypes::SystemMessage *sm)
{
switch( sm->command )
{
case SystemMessage::StartUp:
{
waitSMReady();
// подождать пока пройдёт инициализация датчиков
// см. activateObject()
msleep(initPause);
PassiveTimer ptAct(activateTimeout);
while( !activated && !ptAct.checkTime() )
{
cout << myname << "(sysCommand): wait activate..." << endl;
msleep(300);
if( activated )
break;
}
if( !activated )
dlog[Debug::CRIT] << myname << "(sysCommand): ************* don`t activate?! ************" << endl;
{
UniSetTypes::uniset_mutex_lock l(mutex_start, 10000);
askSensors(UniversalIO::UIONotify);
}
thr->start();
}
case SystemMessage::FoldUp:
case SystemMessage::Finish:
askSensors(UniversalIO::UIODontNotify);
break;
case SystemMessage::WatchDog:
{
// ОПТИМИЗАЦИЯ (защита от двойного перезаказа при старте)
// Если идёт локальная работа
// (т.е. UDPReceiver запущен в одном процессе с SharedMemory2)
// то обрабатывать WatchDog не надо, т.к. мы и так ждём готовности SM
// при заказе датчиков, а если SM вылетит, то вместе с этим процессом(UDPReceiver)
if( shm->isLocalwork() )
break;
askSensors(UniversalIO::UIONotify);
}
break;
case SystemMessage::LogRotate:
{
// переоткрываем логи
unideb << myname << "(sysCommand): logRotate" << std::endl;
string fname = unideb.getLogFile();
if( !fname.empty() )
{
unideb.logFile(fname);
unideb << myname << "(sysCommand): ***************** UNIDEB LOG ROTATE *****************" << std::endl;
}
dlog << myname << "(sysCommand): logRotate" << std::endl;
fname = dlog.getLogFile();
if( !fname.empty() )
{
dlog.logFile(fname);
dlog << myname << "(sysCommand): ***************** dlog LOG ROTATE *****************" << std::endl;
}
}
break;
default:
break;
}
}
// ------------------------------------------------------------------------------------------
void UDPReceiver::askSensors( UniversalIO::UIOCommand cmd )
{
if( !shm->waitSMworking(test_id,activateTimeout,50) )
{
ostringstream err;
err << myname
<< "(askSensors): Не дождались готовности(work) SharedMemory к работе в течение "
<< activateTimeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
kill(SIGTERM,getpid()); // прерываем (перезапускаем) процесс...
throw SystemError(err.str());
}
}
// ------------------------------------------------------------------------------------------
void UDPReceiver::sensorInfo( UniSetTypes::SensorMessage* sm )
{
}
// ------------------------------------------------------------------------------------------
bool UDPReceiver::activateObject()
{
// блокирование обработки Starsp
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated = false;
UniSetTypes::uniset_mutex_lock l(mutex_start, 5000);
UniSetObject_LT::activateObject();
initIterators();
activated = true;
}
return true;
}
// ------------------------------------------------------------------------------------------
void UDPReceiver::sigterm( int signo )
{
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false;
udp->disconnect();
UniSetObject_LT::sigterm(signo);
}
// ------------------------------------------------------------------------------------------
void UDPReceiver::initIterators()
{
shm->initAIterator(aitHeartBeat);
}
// -----------------------------------------------------------------------------
void UDPReceiver::help_print( int argc, char* argv[] )
{
cout << "--udp-polltime msec - Пауза между опросаом карт. По умолчанию 200 мсек." << endl;
cout << "--udp-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl;
cout << "--udp-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--udp-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--udp-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl;
cout << "--udp-notRespondSensor - датчик связи для данного процесса " << endl;
cout << "--udp-sm-ready-timeout - время на ожидание старта SM" << endl;
cout << " Настройки протокола RS: " << endl;
cout << "--udp-dev devname - файл устройства" << endl;
cout << "--udp-speed - Скорость обмена (9600,19920,38400,57600,115200)." << endl;
cout << "--udp-my-addr - адрес текущего узла" << endl;
cout << "--udp-recv-timeout - Таймаут на ожидание ответа." << endl;
}
// -----------------------------------------------------------------------------
UDPReceiver* UDPReceiver::init_udpreceiver( int argc, char* argv[], UniSetTypes::ObjectId icID, SharedMemory* ic )
{
string name = conf->getArgParam("--udp-name","UDPReceiver1");
if( name.empty() )
{
cerr << "(udpexchange): Не задан name'" << endl;
return 0;
}
ObjectId ID = conf->getObjectID(name);
if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(udpexchange): идентификатор '" << name
<< "' не найден в конф. файле!"
<< " в секции " << conf->getObjectsSection() << endl;
return 0;
}
dlog[Debug::INFO] << "(rsexchange): name = " << name << "(" << ID << ")" << endl;
return new UDPReceiver(ID,icID,ic);
}
// -----------------------------------------------------------------------------
#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_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UDPSender.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UDPSender::UDPSender( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic ):
UniSetObject_LT(objId),
shm(0),
initPause(0),
udp(0),
activated(false),
dlist(100),
maxItem(0)
{
if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(UDPSender): objId=-1?!! Use --udp-name" );
// xmlNode* cnode = conf->getNode(myname);
cnode = conf->getNode(myname);
if( cnode == NULL )
throw UniSetTypes::SystemError("(UDPSender): Not find conf-node for " + myname );
shm = new SMInterface(shmId,&ui,objId,ic);
UniXML_iterator it(cnode);
// определяем фильтр
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;
// ---------- init RS ----------
// UniXML_iterator it(cnode);
string s_host = conf->getArgParam("--udp-host",it.getProp("host"));
if( s_host.empty() )
throw UniSetTypes::SystemError(myname+"(UDPSender): Unknown host. Use --udp-host" );
port = conf->getArgInt("--udp-port",it.getProp("port"));
if( port <= 0 )
throw UniSetTypes::SystemError(myname+"(UDPSender): Unknown port address. Use --udp-port" );
bool broadcast = conf->getArgInt("--udp-broadcast",it.getProp("broadcast"));
host = s_host.c_str();
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UDPSender): UDP set to " << s_host << ":" << port
<< " broadcast=" << broadcast
<< endl;
try
{
if( !broadcast )
udp = new ost::UDPSocket();
else
udp = new ost::UDPBroadcast(host,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << myname << "(init): " << s.str() << endl;
throw SystemError(s.str());
}
thr = new ThreadCreator<UDPSender>(this, &UDPSender::poll);
sendTimeout = conf->getArgPInt("--udp-send-timeout",it.getProp("sendTimeout"), 5000);
sendtime = conf->getArgPInt("--udp-sendtime",it.getProp("sendtime"), 100);
// -------------------------------
if( shm->isLocalwork() )
{
readConfiguration();
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
}
else
ic->addReadItem( sigc::mem_fun(this,&UDPSender::readItem) );
// ********** HEARTBEAT *************
string heart = conf->getArgParam("--udp-heartbeat-id",it.getProp("heartbeat_id"));
if( !heart.empty() )
{
sidHeartBeat = conf->getSensorID(heart);
if( sidHeartBeat == DefaultObjectId )
{
ostringstream err;
err << myname << ": не найден идентификатор для датчика 'HeartBeat' " << heart;
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
int heartbeatTime = getHeartBeatTime();
if( heartbeatTime )
ptHeartBeat.setTiming(heartbeatTime);
else
ptHeartBeat.setTiming(UniSetTimer::WaitUpTime);
maxHeartBeat = conf->getArgPInt("--udp-heartbeat-max", it.getProp("heartbeat_max"), 10);
test_id = sidHeartBeat;
}
else
{
test_id = conf->getSensorID("TestMode_S");
if( test_id == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): test_id unknown. 'TestMode_S' not found...";
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl;
activateTimeout = conf->getArgPInt("--activate-timeout", 20000);
timeout_t msec = conf->getArgPInt("--udp-timeout",it.getProp("timeout"), 3000);
dlog[Debug::INFO] << myname << "(init): udp-timeout=" << msec << " msec" << endl;
}
// -----------------------------------------------------------------------------
UDPSender::~UDPSender()
{
delete udp;
delete shm;
delete thr;
}
// -----------------------------------------------------------------------------
void UDPSender::waitSMReady()
{
// waiting for SM is ready...
int ready_timeout = conf->getArgInt("--udp-sm-ready-timeout","15000");
if( ready_timeout == 0 )
ready_timeout = 15000;
else if( ready_timeout < 0 )
ready_timeout = UniSetTimer::WaitUpTime;
if( !shm->waitSMready(ready_timeout,50) )
{
ostringstream err;
err << myname << "(waitSMReady): Не дождались готовности SharedMemory к работе в течение " << ready_timeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
throw SystemError(err.str());
}
}
// -----------------------------------------------------------------------------
void UDPSender::step()
{
if( !activated )
return;
if( sidHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
shm->localSaveValue(aitHeartBeat,sidHeartBeat,maxHeartBeat,getId());
ptHeartBeat.reset();
}
catch(Exception& ex)
{
dlog[Debug::CRIT] << myname
<< "(step): (hb) " << ex << std::endl;
}
}
}
// -----------------------------------------------------------------------------
void UDPSender::poll()
{
dlist.resize(maxItem);
dlog[Debug::INFO] << myname << "(init): dlist size = " << dlist.size() << endl;
try
{
udp->setPeer(host,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
{
send();
}
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;
}
msleep(sendtime);
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
void UDPSender::send()
{
cout << myname << ": send..." << endl;
UniSetUDP::UDPHeader h;
h.nodeID = conf->getLocalNode();
h.procID = getId();
h.dcount = mypack.size();
// receive
size_t ret = udp->send((char*)(&h),sizeof(h));
if( ret<(size_t)sizeof(h) )
{
cerr << myname << "(send data header): ret=" << ret << " sizeof=" << sizeof(h) << endl;
return;
}
/*! \todo Подумать нужен ли здесь mutex */
UniSetUDP::UDPMessage::UDPDataList::iterator it = mypack.dlist.begin();
for( ; it!=mypack.dlist.end(); ++it )
{
cout << myname << "(send): " << (*it) << endl;
size_t ret = udp->send((char*)(&(*it)),sizeof(*it));
if( ret<(size_t)sizeof(*it) )
{
cerr << myname << "(send data): ret=" << ret << " sizeof=" << sizeof(*it) << endl;
break;
}
}
}
// -----------------------------------------------------------------------------
void UDPSender::processingMessage(UniSetTypes::VoidMessage *msg)
{
try
{
switch(msg->type)
{
case UniSetTypes::Message::SysCommand:
{
UniSetTypes::SystemMessage sm( msg );
sysCommand( &sm );
}
break;
case Message::SensorInfo:
{
SensorMessage sm( msg );
sensorInfo(&sm);
}
break;
default:
break;
}
}
catch( SystemError& ex )
{
dlog[Debug::CRIT] << myname << "(SystemError): " << ex << std::endl;
// throw SystemError(ex);
raise(SIGTERM);
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << myname << "(processingMessage): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(processingMessage): catch ...\n";
}
}
// -----------------------------------------------------------------------------
void UDPSender::sysCommand(UniSetTypes::SystemMessage *sm)
{
switch( sm->command )
{
case SystemMessage::StartUp:
{
waitSMReady();
// подождать пока пройдёт инициализация датчиков
// см. activateObject()
msleep(initPause);
PassiveTimer ptAct(activateTimeout);
while( !activated && !ptAct.checkTime() )
{
cout << myname << "(sysCommand): wait activate..." << endl;
msleep(300);
if( activated )
break;
}
if( !activated )
dlog[Debug::CRIT] << myname << "(sysCommand): ************* don`t activate?! ************" << endl;
{
UniSetTypes::uniset_mutex_lock l(mutex_start, 10000);
askSensors(UniversalIO::UIONotify);
}
thr->start();
}
case SystemMessage::FoldUp:
case SystemMessage::Finish:
askSensors(UniversalIO::UIODontNotify);
break;
case SystemMessage::WatchDog:
{
// ОПТИМИЗАЦИЯ (защита от двойного перезаказа при старте)
// Если идёт локальная работа
// (т.е. UDPSender запущен в одном процессе с SharedMemory2)
// то обрабатывать WatchDog не надо, т.к. мы и так ждём готовности SM
// при заказе датчиков, а если SM вылетит, то вместе с этим процессом(UDPSender)
if( shm->isLocalwork() )
break;
askSensors(UniversalIO::UIONotify);
}
break;
case SystemMessage::LogRotate:
{
// переоткрываем логи
unideb << myname << "(sysCommand): logRotate" << std::endl;
string fname = unideb.getLogFile();
if( !fname.empty() )
{
unideb.logFile(fname);
unideb << myname << "(sysCommand): ***************** UNIDEB LOG ROTATE *****************" << std::endl;
}
dlog << myname << "(sysCommand): logRotate" << std::endl;
fname = dlog.getLogFile();
if( !fname.empty() )
{
dlog.logFile(fname);
dlog << myname << "(sysCommand): ***************** dlog LOG ROTATE *****************" << std::endl;
}
}
break;
default:
break;
}
}
// ------------------------------------------------------------------------------------------
void UDPSender::askSensors( UniversalIO::UIOCommand cmd )
{
if( !shm->waitSMworking(test_id,activateTimeout,50) )
{
ostringstream err;
err << myname
<< "(askSensors): Не дождались готовности(work) SharedMemory к работе в течение "
<< activateTimeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
kill(SIGTERM,getpid()); // прерываем (перезапускаем) процесс...
throw SystemError(err.str());
}
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
try
{
shm->askSensor(it->si.id,cmd);
}
catch( UniSetTypes::Exception& ex )
{
dlog[Debug::WARN] << myname << "(askSensors): " << ex << std::endl;
}
catch(...){}
}
}
// ------------------------------------------------------------------------------------------
void UDPSender::sensorInfo( UniSetTypes::SensorMessage* sm )
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it )
{
if( it->si.id == sm->id )
{
uniset_spin_lock lock(it->val_lock);
it->val = sm->value;
if( it->pack_it != mypack.dlist.end() )
it->pack_it->val = sm->value;
}
break;
}
}
// ------------------------------------------------------------------------------------------
bool UDPSender::activateObject()
{
// блокирование обработки StarUp
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated = false;
UniSetTypes::uniset_mutex_lock l(mutex_start, 5000);
UniSetObject_LT::activateObject();
initIterators();
activated = true;
}
return true;
}
// ------------------------------------------------------------------------------------------
void UDPSender::sigterm( int signo )
{
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false;
udp->disconnect();
UniSetObject_LT::sigterm(signo);
}
// ------------------------------------------------------------------------------------------
void UDPSender::readConfiguration()
{
// readconf_ok = false;
xmlNode* root = conf->getXMLSensorsSection();
if(!root)
{
ostringstream err;
err << myname << "(readConfiguration): не нашли корневого раздела <sensors>";
throw SystemError(err.str());
}
UniXML_iterator it(root);
if( !it.goChildren() )
{
std::cerr << myname << "(readConfiguration): раздел <sensors> не содержит секций ?!!\n";
return;
}
for( ;it.getCurrent(); it.goNext() )
{
if( check_item(it) )
initItem(it);
}
// readconf_ok = true;
}
// ------------------------------------------------------------------------------------------
bool UDPSender::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 UDPSender::readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec )
{
if( check_item(it) )
initItem(it);
return true;
}
// ------------------------------------------------------------------------------------------
bool UDPSender::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_it = (mypack.dlist.end()--);
if( maxItem >= dlist.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 UDPSender::initIterators()
{
DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); it++ )
{
shm->initDIterator(it->dit);
shm->initAIterator(it->ait);
}
shm->initAIterator(aitHeartBeat);
}
// -----------------------------------------------------------------------------
void UDPSender::help_print( int argc, char* argv[] )
{
cout << "--udp-sendtime msec - Пауза между опросами. По умолчанию 200 мсек." << endl;
cout << "--udp-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl;
cout << "--udp-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--udp-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--udp-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl;
cout << "--udp-sm-ready-timeout - время на ожидание старта SM" << endl;
cout << " Настройки протокола UDP: " << endl;
cout << "--udp-host [ip|hostname] - Адрес сервера" << endl;
cout << "--udp-port - Порт." << endl;
cout << "--udp-send-timeout - Таймаут на посылку ответа." << endl;
}
// -----------------------------------------------------------------------------
UDPSender* UDPSender::init_udpsender( int argc, char* argv[], UniSetTypes::ObjectId icID, SharedMemory* ic )
{
string name = conf->getArgParam("--udp-name","UDPSender1");
if( name.empty() )
{
cerr << "(UDPSender): Не задан name'" << endl;
return 0;
}
ObjectId ID = conf->getObjectID(name);
if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(UDPSender): идентификатор '" << name
<< "' не найден в конф. файле!"
<< " в секции " << conf->getObjectsSection() << endl;
return 0;
}
dlog[Debug::INFO] << "(rsexchange): name = " << name << "(" << ID << ")" << endl;
return new UDPSender(ID,icID,ic);
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, UDPSender::UItem& p )
{
return os << " sid=" << p.si.id;
}
// -----------------------------------------------------------------------------
#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_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UNetExchange.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
UNetExchange::UNetExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic ):
UniSetObject_LT(objId),
shm(0),
initPause(0),
activated(false),
no_sender(false),
sender(0)
{
if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(UNetExchange): objId=-1?!! Use --unet-name" );
// xmlNode* cnode = conf->getNode(myname);
cnode = conf->getNode(myname);
if( cnode == NULL )
throw UniSetTypes::SystemError("(UNetExchange): Not found conf-node for " + myname );
shm = new SMInterface(shmId,&ui,objId,ic);
UniXML_iterator it(cnode);
// определяем фильтр
s_field = conf->getArgParam("--unet-filter-field");
s_fvalue = conf->getArgParam("--unet-filter-value");
dlog[Debug::INFO] << myname << "(init): read fileter-field='" << s_field
<< "' filter-value='" << s_fvalue << "'" << endl;
int recvTimeout = conf->getArgPInt("--unet-recv-timeout",it.getProp("recvTimeout"), 5000);
int lostTimeout = conf->getArgPInt("--unet-lost-timeout",it.getProp("lostTimeout"), recvTimeout);
int recvpause = conf->getArgPInt("--unet-recvpause",it.getProp("recvpause"), 10);
int sendpause = conf->getArgPInt("--unet-sendpause",it.getProp("sendpause"), 150);
int updatepause = conf->getArgPInt("--unet-updatepause",it.getProp("updatepause"), 100);
steptime = conf->getArgPInt("--unet-steptime",it.getProp("steptime"), 1000);
int maxDiff = conf->getArgPInt("--unet-maxdifferense",it.getProp("maxDifferense"), 1000);
int maxProcessingCount = conf->getArgPInt("--unet-maxprocessingcount",it.getProp("maxProcessingCount"), 100);
no_sender = conf->getArgInt("--unet-nosender",it.getProp("nosender"));
xmlNode* nodes = conf->getXMLNodesSection();
if( !nodes )
throw UniSetTypes::SystemError("(UNetExchange): Not found <nodes>");
UniXML_iterator n_it(nodes);
if( !n_it.goChildren() )
throw UniSetTypes::SystemError("(UNetExchange): Items not found for <nodes>");
for( ; n_it.getCurrent(); n_it.goNext() )
{
string h(n_it.getProp("ip"));
if( !n_it.getProp("unet_ip").empty() )
h = n_it.getProp("unet_ip");
int p = n_it.getIntProp("id");
if( !n_it.getProp("unet_port").empty() )
p = n_it.getIntProp("unet_port");
string n(n_it.getProp("name"));
if( n == conf->getLocalNodeName() )
{
dlog[Debug::INFO] << myname << "(init): init sender.. my node " << n_it.getProp("name") << endl;
sender = new UNetSender(h,p,shm,s_field,s_fvalue,ic);
sender->setSendPause(sendpause);
continue;
}
if( !n_it.getProp("unet_ignore").empty() )
{
dlog[Debug::INFO] << myname << "(init): unet_ignore.. for " << n_it.getProp("name") << endl;
continue;
}
dlog[Debug::INFO] << myname << "(init): add UNetReceiver for " << h << ":" << p << endl;
if( checkExistUNetHost(h,p) )
{
dlog[Debug::INFO] << myname << "(init): " << h << ":" << p << " already added! Ignore.." << endl;
continue;
}
UNetReceiver* r = new UNetReceiver(h,p,shm);
r->setReceiveTimeout(recvTimeout);
r->setLostTimeout(lostTimeout);
r->setReceivePause(recvpause);
r->setUpdatePause(updatepause);
r->setMaxDifferens(maxDiff);
r->setMaxProcessingCount(maxProcessingCount);
recvlist.push_back(r);
}
// -------------------------------
// ********** HEARTBEAT *************
string heart = conf->getArgParam("--unet-heartbeat-id",it.getProp("heartbeat_id"));
if( !heart.empty() )
{
sidHeartBeat = conf->getSensorID(heart);
if( sidHeartBeat == DefaultObjectId )
{
ostringstream err;
err << myname << ": не найден идентификатор для датчика 'HeartBeat' " << heart;
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
int heartbeatTime = getHeartBeatTime();
if( heartbeatTime )
ptHeartBeat.setTiming(heartbeatTime);
else
ptHeartBeat.setTiming(UniSetTimer::WaitUpTime);
maxHeartBeat = conf->getArgPInt("--unet-heartbeat-max", it.getProp("heartbeat_max"), 10);
test_id = sidHeartBeat;
}
else
{
test_id = conf->getSensorID("TestMode_S");
if( test_id == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): test_id unknown. 'TestMode_S' not found...";
dlog[Debug::CRIT] << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl;
activateTimeout = conf->getArgPInt("--activate-timeout", 20000);
timeout_t msec = conf->getArgPInt("--unet-timeout",it.getProp("timeout"), 3000);
dlog[Debug::INFO] << myname << "(init): udp-timeout=" << msec << " msec" << endl;
}
// -----------------------------------------------------------------------------
UNetExchange::~UNetExchange()
{
for( ReceiverList::iterator it=recvlist.begin(); it!=recvlist.end(); ++it )
delete (*it);
delete sender;
delete shm;
}
// -----------------------------------------------------------------------------
bool UNetExchange::checkExistUNetHost( const std::string addr, ost::tpport_t port )
{
ost::IPV4Address a1(addr.c_str());
for( ReceiverList::iterator it=recvlist.begin(); it!=recvlist.end(); ++it )
{
if( (*it)->getAddress() == a1.getAddress() && (*it)->getPort() == port )
return true;
}
return false;
}
// -----------------------------------------------------------------------------
void UNetExchange::startReceivers()
{
for( ReceiverList::iterator it=recvlist.begin(); it!=recvlist.end(); ++it )
(*it)->start();
}
// -----------------------------------------------------------------------------
void UNetExchange::initSender( const std::string s_host, const ost::tpport_t port, UniXML_iterator& it )
{
if( no_sender )
return;
}
// -----------------------------------------------------------------------------
void UNetExchange::waitSMReady()
{
// waiting for SM is ready...
int ready_timeout = conf->getArgInt("--unet-sm-ready-timeout","15000");
if( ready_timeout == 0 )
ready_timeout = 15000;
else if( ready_timeout < 0 )
ready_timeout = UniSetTimer::WaitUpTime;
if( !shm->waitSMready(ready_timeout,50) )
{
ostringstream err;
err << myname << "(waitSMReady): Не дождались готовности SharedMemory к работе в течение " << ready_timeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
throw SystemError(err.str());
}
}
// -----------------------------------------------------------------------------
void UNetExchange::timerInfo( TimerMessage *tm )
{
if( !activated )
return;
if( tm->id == tmStep )
step();
}
// -----------------------------------------------------------------------------
void UNetExchange::step()
{
if( !activated )
return;
if( sidHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
shm->localSaveValue(aitHeartBeat,sidHeartBeat,maxHeartBeat,getId());
ptHeartBeat.reset();
}
catch(Exception& ex)
{
dlog[Debug::CRIT] << myname << "(step): (hb) " << ex << std::endl;
}
}
}
// -----------------------------------------------------------------------------
void UNetExchange::processingMessage(UniSetTypes::VoidMessage *msg)
{
try
{
switch(msg->type)
{
case UniSetTypes::Message::SysCommand:
{
UniSetTypes::SystemMessage sm( msg );
sysCommand( &sm );
}
break;
case Message::SensorInfo:
{
SensorMessage sm( msg );
sensorInfo(&sm);
}
break;
case Message::Timer:
{
TimerMessage tm(msg);
timerInfo(&tm);
}
break;
default:
break;
}
}
catch( SystemError& ex )
{
dlog[Debug::CRIT] << myname << "(SystemError): " << ex << std::endl;
// throw SystemError(ex);
raise(SIGTERM);
}
catch( Exception& ex )
{
dlog[Debug::CRIT] << myname << "(processingMessage): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(processingMessage): catch ...\n";
}
}
// -----------------------------------------------------------------------------
void UNetExchange::sysCommand( UniSetTypes::SystemMessage *sm )
{
switch( sm->command )
{
case SystemMessage::StartUp:
{
waitSMReady();
// подождать пока пройдёт инициализация датчиков
// см. activateObject()
msleep(initPause);
PassiveTimer ptAct(activateTimeout);
while( !activated && !ptAct.checkTime() )
{
cout << myname << "(sysCommand): wait activate..." << endl;
msleep(300);
if( activated )
break;
}
if( !activated )
dlog[Debug::CRIT] << myname << "(sysCommand): ************* don`t activate?! ************" << endl;
{
UniSetTypes::uniset_mutex_lock l(mutex_start, 10000);
askSensors(UniversalIO::UIONotify);
}
askTimer(tmStep,steptime);
startReceivers();
if( sender )
sender->start();
}
case SystemMessage::FoldUp:
case SystemMessage::Finish:
askSensors(UniversalIO::UIODontNotify);
break;
case SystemMessage::WatchDog:
{
// ОПТИМИЗАЦИЯ (защита от двойного перезаказа при старте)
// Если идёт локальная работа
// (т.е. UNetExchange запущен в одном процессе с SharedMemory2)
// то обрабатывать WatchDog не надо, т.к. мы и так ждём готовности SM
// при заказе датчиков, а если SM вылетит, то вместе с этим процессом(UNetExchange)
if( shm->isLocalwork() )
break;
askSensors(UniversalIO::UIONotify);
}
break;
case SystemMessage::LogRotate:
{
// переоткрываем логи
unideb << myname << "(sysCommand): logRotate" << std::endl;
string fname = unideb.getLogFile();
if( !fname.empty() )
{
unideb.logFile(fname);
unideb << myname << "(sysCommand): ***************** UNIDEB LOG ROTATE *****************" << std::endl;
}
dlog << myname << "(sysCommand): logRotate" << std::endl;
fname = dlog.getLogFile();
if( !fname.empty() )
{
dlog.logFile(fname);
dlog << myname << "(sysCommand): ***************** dlog LOG ROTATE *****************" << std::endl;
}
}
break;
default:
break;
}
}
// ------------------------------------------------------------------------------------------
void UNetExchange::askSensors( UniversalIO::UIOCommand cmd )
{
if( !shm->waitSMworking(test_id,activateTimeout,50) )
{
ostringstream err;
err << myname
<< "(askSensors): Не дождались готовности(work) SharedMemory к работе в течение "
<< activateTimeout << " мсек";
dlog[Debug::CRIT] << err.str() << endl;
kill(SIGTERM,getpid()); // прерываем (перезапускаем) процесс...
throw SystemError(err.str());
}
}
// ------------------------------------------------------------------------------------------
void UNetExchange::sensorInfo( UniSetTypes::SensorMessage* sm )
{
if( sender )
sender->update(sm->id,sm->value);
}
// ------------------------------------------------------------------------------------------
bool UNetExchange::activateObject()
{
// блокирование обработки Starsp
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated = false;
UniSetTypes::uniset_mutex_lock l(mutex_start, 5000);
UniSetObject_LT::activateObject();
initIterators();
activated = true;
}
return true;
}
// ------------------------------------------------------------------------------------------
void UNetExchange::sigterm( int signo )
{
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false;
UniSetObject_LT::sigterm(signo);
}
// ------------------------------------------------------------------------------------------
void UNetExchange::initIterators()
{
shm->initAIterator(aitHeartBeat);
}
// -----------------------------------------------------------------------------
void UNetExchange::help_print( int argc, char* argv[] )
{
cout << "--unet-recvpause msec - Пауза между получением пакетов. По умолчанию 10 мсек." << endl;
cout << "--unet-updatepause msec - Пауза между обновлением данных в SM. По умолчанию 100 мсек." << endl;
cout << "--unet-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl;
cout << "--unet-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--unet-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--unet-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl;
cout << "--unet-notRespondSensor - датчик связи для данного процесса " << endl;
cout << "--unet-sm-ready-timeout - время на ожидание старта SM" << endl;
cout << " Настройки протокола RS: " << endl;
}
// -----------------------------------------------------------------------------
UNetExchange* UNetExchange::init_unetexchange( int argc, char* argv[], UniSetTypes::ObjectId icID, SharedMemory* ic )
{
string name = conf->getArgParam("--unet-name","UNetExchange1");
if( name.empty() )
{
cerr << "(unetexchange): Не задан name'" << endl;
return 0;
}
ObjectId ID = conf->getObjectID(name);
if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(unetexchange): идентификатор '" << name
<< "' не найден в конф. файле!"
<< " в секции " << conf->getObjectsSection() << endl;
return 0;
}
dlog[Debug::INFO] << "(unetexchange): name = " << name << "(" << ID << ")" << endl;
return new UNetExchange(ID,icID,ic);
}
// -----------------------------------------------------------------------------
#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_
// -----------------------------------------------------------------------------
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UNetReceiver.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
bool UNetReceiver::PacketCompare::operator()(const UniSetUDP::UDPMessage& lhs,
const UniSetUDP::UDPMessage& rhs) const
{
// if( lhs.msg.header.num == rhs.msg.header.num )
// return (lhs.msg < rhs.msg);
return lhs.msg.header.num > rhs.msg.header.num;
}
// ------------------------------------------------------------------------------------------
UNetReceiver::UNetReceiver( const std::string s_host, const ost::tpport_t port, SMInterface* smi ):
shm(smi),
recvpause(10),
updatepause(100),
udp(0),
recvTimeout(5000),
lostTimeout(5000),
lostPackets(0),
activated(false),
r_thr(0),
u_thr(0),
pnum(0),
maxDifferens(1000),
waitClean(false),
rnum(0),
maxProcessingCount(100),
icache(200),
cache_init_ok(false)
{
{
ostringstream s;
s << "(" << s_host << ":" << port << ")";
myname = s.str();
}
try
{
// ost::IPV4Cidr ci(s_host.c_str());
// addr = ci.getBroadcast();
// cerr << "****************** addr: " << addr << endl;
addr = s_host.c_str();
udp = new ost::UDPDuplex(addr,port);
}
catch( ost::SockException& e )
{
ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString();
dlog[Debug::CRIT] << myname << "(init): " << s.str() << std::endl;
throw SystemError(s.str());
}
r_thr = new ThreadCreator<UNetReceiver>(this, &UNetReceiver::receive);
u_thr = new ThreadCreator<UNetReceiver>(this, &UNetReceiver::update);
ptRecvTimeout.setTiming(recvTimeout);
}
// -----------------------------------------------------------------------------
UNetReceiver::~UNetReceiver()
{
delete r_thr;
delete u_thr;
delete udp;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setReceiveTimeout( timeout_t msec )
{
recvTimeout = msec;
ptRecvTimeout.setTiming(msec);
}
// -----------------------------------------------------------------------------
void UNetReceiver::setLostTimeout( timeout_t msec )
{
lostTimeout = msec;
ptLostTimeout.setTiming(msec);
}
// -----------------------------------------------------------------------------
void UNetReceiver::setReceivePause( timeout_t msec )
{
recvpause = msec;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setUpdatePause( timeout_t msec )
{
updatepause = msec;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setMaxProcessingCount( int set )
{
maxProcessingCount = set;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setMaxDifferens( unsigned long set )
{
maxDifferens = set;
}
// -----------------------------------------------------------------------------
void UNetReceiver::start()
{
if( !activated )
{
activated = true;
u_thr->start();
r_thr->start();
}
}
// -----------------------------------------------------------------------------
void UNetReceiver::update()
{
cerr << "******************* udpate start" << endl;
while(activated)
{
try
{
real_update();
}
catch( UniSetTypes::Exception& ex)
{
dlog[Debug::CRIT] << myname << "(update): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(update): catch ..." << std::endl;
}
msleep(updatepause);
}
}
// -----------------------------------------------------------------------------
void UNetReceiver::real_update()
{
UniSetUDP::UDPMessage p;
// обрабатываем пока, очередь либо не опустеет
// либо обнаружится "дырка" в последовательности
// но при этом обрабатываем не больше maxProcessingCount
// за один раз..
int k = maxProcessingCount;
while( k>0 )
{
{ // lock qpack
uniset_mutex_lock l(packMutex);
if( qpack.empty() )
return;
p = qpack.top();
unsigned long sub = labs(p.msg.header.num - pnum);
if( pnum > 0 )
{
// если sub > maxDifferens
// значит это просто "разрыв"
// и нам ждать lostTimeout не надо
// сразу начинаем обрабатывать новые пакеты
// а если > 1 && < maxDifferens
// значит это временная "дырка"
// и надо подождать lostTimeout
// чтобы констатировать потерю пакета..
if( sub > 1 && sub < maxDifferens )
{
if( !ptLostTimeout.checkTime() )
return;
lostPackets++;
}
else if( p.msg.header.num == pnum )
{
/* а что делать если идут повторные пакеты ?!
* для надёжности лучше обрабатывать..
* для "оптимизации".. лучше игнорировать
*/
qpack.pop(); // пока выбрали вариант "оптимизации"
continue;
}
}
ptLostTimeout.reset();
// удаляем из очереди, только если
// всё в порядке с последовательностью..
qpack.pop();
pnum = p.msg.header.num;
} // unlock qpack
k--;
// cerr << myname << "(update): " << p.msg.header << endl;
initCache(p, !cache_init_ok);
for( size_t i=0; i<p.msg.header.dcount; i++ )
{
try
{
UniSetUDP::UDPData& d = p.msg.dat[i];
ItemInfo& ii(icache[i]);
if( ii.id != d.id )
{
dlog[Debug::WARN] << myname << "(update): reinit cache for sid=" << d.id << endl;
ii.id = d.id;
shm->initAIterator(ii.ait);
shm->initDIterator(ii.dit);
}
if( ii.iotype == UniversalIO::DigitalInput )
shm->localSaveState(ii.dit,d.id,d.val,shm->ID());
else if( ii.iotype == UniversalIO::AnalogInput )
shm->localSaveValue(ii.ait,d.id,d.val,shm->ID());
else if( ii.iotype == UniversalIO::AnalogOutput )
shm->localSetValue(ii.ait,d.id,d.val,shm->ID());
else if( ii.iotype == UniversalIO::DigitalOutput )
shm->localSetState(ii.dit,d.id,d.val,shm->ID());
else
dlog[Debug::CRIT] << myname << "(update): Unknown iotype for sid=" << d.id << endl;
}
catch( UniSetTypes::Exception& ex)
{
dlog[Debug::CRIT] << myname << "(update): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(update): catch ..." << std::endl;
}
}
}
}
// -----------------------------------------------------------------------------
void UNetReceiver::receive()
{
cerr << "******************* receive start" << endl;
ptRecvTimeout.setTiming(recvTimeout);
while( activated )
{
try
{
if( recv() )
ptRecvTimeout.reset();
}
catch( ost::SockException& e )
{
cerr << e.getString() << ": " << e.getSystemErrorString() << endl;
}
catch( UniSetTypes::Exception& ex)
{
cerr << myname << "(poll): " << ex << std::endl;
}
catch(...)
{
cerr << myname << "(poll): catch ..." << std::endl;
}
msleep(recvpause);
}
cerr << "************* execute FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
bool UNetReceiver::recv()
{
if( !udp->isInputReady(recvTimeout) )
return false;
size_t ret = udp->UDPReceive::receive(&(pack.msg),sizeof(pack.msg));
if( ret < sizeof(UniSetUDP::UDPHeader) )
{
dlog[Debug::CRIT] << myname << "(receive): FAILED header ret=" << ret << " sizeof=" << sizeof(UniSetUDP::UDPHeader) << endl;
return false;
}
size_t sz = pack.msg.header.dcount * sizeof(UniSetUDP::UDPData) + sizeof(UniSetUDP::UDPHeader);
if( ret < sz )
{
dlog[Debug::CRIT] << myname << "(receive): FAILED data ret=" << ret << " sizeof=" << sz
<< " packnum=" << pack.msg.header.num << endl;
return false;
}
if( rnum>0 && labs(pack.msg.header.num - rnum) > maxDifferens )
{
/* А что делать если мы уже ждём и ещё не "разгребли предыдущее".. а тут уже повторный "разрыв"
* Можно откинуть всё.. что сложили во временную очередь и заново "копить" (но тогда теряем информацию)
* А можно породолжать складывать во временную, но тогда есть риск "никогда" не разгрести временную
* очередь, при "частых обрывах". Потому-что update будет на каждом разрыве ждать ещё lostTimeout..
*/
// Пока выбираю.. чистить qtmp. Это будет соотвествовать логике работы с картами у которых ограничен буфер приёма.
// Обычно "кольцевой". Т.е. если не успели обработать и "вынуть" из буфера информацию.. он будет переписан новыми данными
if( waitClean )
{
dlog[Debug::CRIT] << myname << "(receive): reset qtmp.." << endl;
while( !qtmp.empty() )
qtmp.pop();
}
waitClean = true;
}
rnum = pack.msg.header.num;
// cerr << myname << "(receive): recv DATA OK. ret=" << ret << " sizeof=" << sz
// << " header: " << pack.msg.header
// << " waitClean=" << waitClean
// << endl;
{ // lock qpack
uniset_mutex_lock l(packMutex,500);
if( !waitClean )
{
qpack.push(pack);
return true;
}
if( !qpack.empty() )
{
// cerr << myname << "(receive): copy to qtmp..."
// << " header: " << pack.msg.header
// << endl;
qtmp.push(pack);
}
else
{
// cerr << myname << "(receive): copy from qtmp..." << endl;
// очередь освободилась..
// то копируем в неё всё что набралось...
while( !qtmp.empty() )
{
qpack.push(qtmp.top());
qtmp.pop();
}
// не забываем и текущий поместить в очередь..
qpack.push(pack);
waitClean = false;
}
} // unlock qpack
return true;
}
// -----------------------------------------------------------------------------
void UNetReceiver::initIterators()
{
for( ItemVec::iterator it=icache.begin(); it!=icache.end(); ++it )
{
shm->initAIterator(it->ait);
shm->initDIterator(it->dit);
}
}
// -----------------------------------------------------------------------------
void UNetReceiver::initCache( UniSetUDP::UDPMessage& pack, bool force )
{
if( !force && pack.msg.header.dcount == icache.size() )
return;
dlog[Debug::INFO] << myname << ": init icache.." << endl;
cache_init_ok = true;
icache.resize(pack.msg.header.dcount);
for( size_t i=0; i<icache.size(); i++ )
{
ItemInfo& d(icache[i]);
if( d.id != pack.msg.dat[i].id )
{
d.id = pack.msg.dat[i].id;
d.iotype = conf->getIOType(d.id);
shm->initAIterator(d.ait);
shm->initDIterator(d.dit);
}
}
}
// -----------------------------------------------------------------------------
#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-файле # не забывайте править версию в pc-файле
UNET2_VER=@LIBVER@ UNET2_VER=@LIBVER@
...@@ -19,6 +19,11 @@ libUniSetUNet2_la_SOURCES = UDPPacket.cc UNetReceiver.cc UNetSender.cc UNetExch ...@@ -19,6 +19,11 @@ libUniSetUNet2_la_SOURCES = UDPPacket.cc UNetReceiver.cc UNetSender.cc UNetExch
$(SIGC_LIBS) $(COMCPP_LIBS) $(SIGC_LIBS) $(COMCPP_LIBS)
@PACKAGE@_unetexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS) $(COMCPP_CFLAGS) @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 # install
devel_include_HEADERS = *.h devel_include_HEADERS = *.h
devel_includedir = $(pkgincludedir)/extensions devel_includedir = $(pkgincludedir)/extensions
...@@ -27,4 +32,4 @@ pkgconfigdir = $(libdir)/pkgconfig ...@@ -27,4 +32,4 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libUniSetUNet2.pc pkgconfig_DATA = libUniSetUNet2.pc
all-local: 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 ) ...@@ -8,38 +8,181 @@ std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPHeader& p )
return os << "nodeID=" << p.nodeID return os << "nodeID=" << p.nodeID
<< " procID=" << p.procID << " procID=" << p.procID
<< " dcount=" << p.dcount << " dcount=" << p.dcount
<< " acount=" << p.acount
<< " pnum=" << p.num; << " 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; return os << "id=" << p.id << " val=" << p.val;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
std::ostream& UniSetUDP::operator<<( std::ostream& os, UniSetUDP::UDPMessage& p ) 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; return os;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
UDPMessage::UDPMessage(): UDPMessage::UDPMessage()
count(0) {
}
// -----------------------------------------------------------------------------
size_t UDPMessage::addAData( const UniSetUDP::UDPAData& dat )
{
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::addData( const UniSetUDP::UDPData& dat ) bool UDPMessage::setAData( size_t index, long val )
{ {
if( count >= MaxDataCount ) if( index < MaxACount )
{
a_dat[index].val = val;
return true;
}
return false; 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;
size_t nbyte = index / sizeof(unsigned char);
size_t nbit = index % sizeof(unsigned char);
msg.dat[count] = dat; // выставляем бит
count++; unsigned char d = d_dat[nbyte];
msg.header.dcount = count; if( val )
d |= (1<<nbit);
else
d &= ~(1<<nbit);
d_dat[nbyte] = d;
return true; return true;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool UDPMessage::addData( long id, long val) 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) );
}
// -----------------------------------------------------------------------------
size_t UDPMessage::transport_msg( UDPPacket& p )
{
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 )
{ {
UDPData d(id,val); getMessage(*this,p);
return addData(d); }
// -----------------------------------------------------------------------------
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 @@ ...@@ -8,59 +8,85 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
namespace UniSetUDP namespace UniSetUDP
{ {
/*! Для оптимизации размера передаваемх данных, но с учёто того, что ID могут идти не подряд.
Сделан следующие формат.
Для аналоговых величин передаётся массив пар "id-value".
Для булевых величин - отдельно массив ID и отдельно битовый массив со значениями,
(по количеству битов такого же размера).
*/
struct UDPHeader 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; unsigned long num;
long nodeID; long nodeID;
long procID; 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 );
friend std::ostream& operator<<( std::ostream& os, UDPHeader* p );
}__attribute__((packed)); }__attribute__((packed));
static unsigned long MaxPacketNum = std::numeric_limits<unsigned long>::max(); static unsigned long MaxPacketNum = std::numeric_limits<unsigned long>::max();
struct UDPData struct UDPAData
{ {
UDPData():id(UniSetTypes::DefaultObjectId),val(0){} UDPAData():id(UniSetTypes::DefaultObjectId),val(0){}
UDPData(long id, long val):id(id),val(val){} UDPAData(long id, long val):id(id),val(val){}
long id; long id;
long val; long val;
friend std::ostream& operator<<( std::ostream& os, UDPData& p ); friend std::ostream& operator<<( std::ostream& os, UDPAData& p );
}__attribute__((packed)); }__attribute__((packed));
static const int MaxDataLen = 8192; static const size_t MaxACount = 100;
static const int MaxDataCount = ( MaxDataLen - sizeof(UniSetUDP::UDPHeader) ) / sizeof(UDPData); static const size_t MaxDCount = 256;
static const size_t MaxDDataCount = MaxDCount / sizeof(unsigned char);
struct DataPacket struct UDPPacket
{ {
UDPHeader header; UDPPacket():len(0){}
UDPData dat[MaxDataCount];
int len;
unsigned char data[ sizeof(UDPHeader) + MaxDCount*sizeof(long) + MaxDDataCount + MaxACount*sizeof(UDPAData) ];
}__attribute__((packed)); }__attribute__((packed));
static const int MaxDataLen = sizeof(UDPPacket);
struct UDPMessage: struct UDPMessage:
public UDPHeader public UDPHeader
{ {
UDPMessage(); UDPMessage();
bool addData( const UDPData& dat ); UDPMessage( UDPPacket& p );
bool addData( long id, long val ); size_t transport_msg( UDPPacket& p );
static size_t getMessage( UDPMessage& m, UDPPacket& p );
inline bool isFull(){ return count<MaxDataCount; } size_t addDData( long id, bool val );
inline int size(){ return count; } bool setDData( size_t index, bool val );
inline int byte_size(){ return count*sizeof(UDPData); } long dID( size_t index );
bool dValue( size_t index );
DataPacket msg; size_t addAData( const UDPAData& dat );
int count; size_t addAData( long id, long val );
bool setAData( size_t index, long val );
friend std::ostream& operator<<( std::ostream& os, UDPMessage& p ); 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_ #endif // UDPPacket_H_
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
using namespace UniSetExtensions; using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
UNetExchange::UNetExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic ): UNetExchange::UNetExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic ):
UniSetObject_LT(objId), UniSetObject_LT(objId),
shm(0), shm(0),
...@@ -17,7 +18,6 @@ sender(0) ...@@ -17,7 +18,6 @@ sender(0)
if( objId == DefaultObjectId ) if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(UNetExchange): objId=-1?!! Use --unet-name" ); throw UniSetTypes::SystemError("(UNetExchange): objId=-1?!! Use --unet-name" );
// xmlNode* cnode = conf->getNode(myname);
cnode = conf->getNode(myname); cnode = conf->getNode(myname);
if( cnode == NULL ) if( cnode == NULL )
throw UniSetTypes::SystemError("(UNetExchange): Not found conf-node for " + myname ); throw UniSetTypes::SystemError("(UNetExchange): Not found conf-node for " + myname );
...@@ -29,7 +29,7 @@ sender(0) ...@@ -29,7 +29,7 @@ sender(0)
// определяем фильтр // определяем фильтр
s_field = conf->getArgParam("--unet-filter-field"); s_field = conf->getArgParam("--unet-filter-field");
s_fvalue = conf->getArgParam("--unet-filter-value"); s_fvalue = conf->getArgParam("--unet-filter-value");
dlog[Debug::INFO] << myname << "(init): read fileter-field='" << s_field dlog[Debug::INFO] << myname << "(init): read filter-field='" << s_field
<< "' filter-value='" << s_fvalue << "'" << endl; << "' filter-value='" << s_fvalue << "'" << endl;
int recvTimeout = conf->getArgPInt("--unet-recv-timeout",it.getProp("recvTimeout"), 5000); int recvTimeout = conf->getArgPInt("--unet-recv-timeout",it.getProp("recvTimeout"), 5000);
...@@ -48,15 +48,38 @@ sender(0) ...@@ -48,15 +48,38 @@ sender(0)
throw UniSetTypes::SystemError("(UNetExchange): Not found <nodes>"); throw UniSetTypes::SystemError("(UNetExchange): Not found <nodes>");
UniXML_iterator n_it(nodes); UniXML_iterator n_it(nodes);
string default_ip(n_it.getProp("unet_broadcast_ip"));
if( !n_it.goChildren() ) if( !n_it.goChildren() )
throw UniSetTypes::SystemError("(UNetExchange): Items not found for <nodes>"); throw UniSetTypes::SystemError("(UNetExchange): Items not found for <nodes>");
for( ; n_it.getCurrent(); n_it.goNext() ) for( ; n_it.getCurrent(); n_it.goNext() )
{ {
string h(n_it.getProp("ip")); if( n_it.getIntProp("unet_ignore") )
if( !n_it.getProp("unet_ip").empty() ) {
h = n_it.getProp("unet_ip"); dlog[Debug::INFO] << myname << "(init): unet_ignore.. for " << n_it.getProp("name") << endl;
continue;
}
// Если указано поле unet_ip непосредственно у узла - берём его
// если указано общий broadcast ip для всех узлов - берём его
string h("");
if( !default_ip.empty() )
h = default_ip;
if( !n_it.getProp("unet_broadcast_ip").empty() )
h = n_it.getProp("unet_broadcast_ip");
if( h.empty() )
{
ostringstream err;
err << myname << "(init): Unkown broadcast IP for " << n_it.getProp("name");
dlog[Debug::CRIT] << err.str() << endl;
throw UniSetTypes::SystemError(err.str());
}
// Если указано поле unet_port - используем его
// Иначе port = идентификатору узла
int p = n_it.getIntProp("id"); int p = n_it.getIntProp("id");
if( !n_it.getProp("unet_port").empty() ) if( !n_it.getProp("unet_port").empty() )
p = n_it.getIntProp("unet_port"); p = n_it.getIntProp("unet_port");
...@@ -70,11 +93,6 @@ sender(0) ...@@ -70,11 +93,6 @@ sender(0)
continue; continue;
} }
if( !n_it.getProp("unet_ignore").empty() )
{
dlog[Debug::INFO] << myname << "(init): unet_ignore.. for " << n_it.getProp("name") << endl;
continue;
}
dlog[Debug::INFO] << myname << "(init): add UNetReceiver for " << h << ":" << p << endl; dlog[Debug::INFO] << myname << "(init): add UNetReceiver for " << h << ":" << p << endl;
...@@ -133,10 +151,6 @@ sender(0) ...@@ -133,10 +151,6 @@ sender(0)
dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl; dlog[Debug::INFO] << myname << "(init): test_id=" << test_id << endl;
activateTimeout = conf->getArgPInt("--activate-timeout", 20000); activateTimeout = conf->getArgPInt("--activate-timeout", 20000);
timeout_t msec = conf->getArgPInt("--unet-timeout",it.getProp("timeout"), 3000);
dlog[Debug::INFO] << myname << "(init): udp-timeout=" << msec << " msec" << endl;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
UNetExchange::~UNetExchange() UNetExchange::~UNetExchange()
...@@ -166,12 +180,6 @@ void UNetExchange::startReceivers() ...@@ -166,12 +180,6 @@ void UNetExchange::startReceivers()
(*it)->start(); (*it)->start();
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetExchange::initSender( const std::string s_host, const ost::tpport_t port, UniXML_iterator& it )
{
if( no_sender )
return;
}
// -----------------------------------------------------------------------------
void UNetExchange::waitSMReady() void UNetExchange::waitSMReady()
{ {
// waiting for SM is ready... // waiting for SM is ready...
...@@ -219,7 +227,7 @@ void UNetExchange::step() ...@@ -219,7 +227,7 @@ void UNetExchange::step()
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetExchange::processingMessage(UniSetTypes::VoidMessage *msg) void UNetExchange::processingMessage( UniSetTypes::VoidMessage *msg )
{ {
try try
{ {
...@@ -262,7 +270,7 @@ void UNetExchange::processingMessage(UniSetTypes::VoidMessage *msg) ...@@ -262,7 +270,7 @@ void UNetExchange::processingMessage(UniSetTypes::VoidMessage *msg)
} }
catch(...) catch(...)
{ {
dlog[Debug::CRIT] << myname << "(processingMessage): catch ...\n"; dlog[Debug::CRIT] << myname << "(processingMessage): catch ..." << std::endl;
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -291,29 +299,31 @@ void UNetExchange::sysCommand( UniSetTypes::SystemMessage *sm ) ...@@ -291,29 +299,31 @@ void UNetExchange::sysCommand( UniSetTypes::SystemMessage *sm )
{ {
UniSetTypes::uniset_mutex_lock l(mutex_start, 10000); UniSetTypes::uniset_mutex_lock l(mutex_start, 10000);
if( shm->isLocalwork() )
askSensors(UniversalIO::UIONotify); askSensors(UniversalIO::UIONotify);
} }
askTimer(tmStep,steptime); askTimer(tmStep,steptime);
startReceivers(); startReceivers();
if( sender ) if( sender )
sender->start(); sender->start();
} }
break;
case SystemMessage::FoldUp: case SystemMessage::FoldUp:
case SystemMessage::Finish: case SystemMessage::Finish:
if( shm->isLocalwork() )
askSensors(UniversalIO::UIODontNotify); askSensors(UniversalIO::UIODontNotify);
break; break;
case SystemMessage::WatchDog: case SystemMessage::WatchDog:
{ {
// ОПТИМИЗАЦИЯ (защита от двойного перезаказа при старте) // ОПТИМИЗАЦИЯ (защита от двойного перезаказа при старте)
// Если идёт локальная работа // Если идёт автономная работа, то нужно заказывать датчики
// (т.е. UNetExchange запущен в одном процессе с SharedMemory2) // если запущены в одном процессе с SharedMemory2,
// то обрабатывать WatchDog не надо, т.к. мы и так ждём готовности SM // то обрабатывать WatchDog не надо, т.к. мы и так ждём готовности SM
// при заказе датчиков, а если SM вылетит, то вместе с этим процессом(UNetExchange) // при заказе датчиков, а если SM вылетит, то вместе с этим процессом(UNetExchange)
if( shm->isLocalwork() ) if( shm->isLocalwork() )
break;
askSensors(UniversalIO::UIONotify); askSensors(UniversalIO::UIONotify);
} }
break; break;
...@@ -357,12 +367,15 @@ void UNetExchange::askSensors( UniversalIO::UIOCommand cmd ) ...@@ -357,12 +367,15 @@ void UNetExchange::askSensors( UniversalIO::UIOCommand cmd )
kill(SIGTERM,getpid()); // прерываем (перезапускаем) процесс... kill(SIGTERM,getpid()); // прерываем (перезапускаем) процесс...
throw SystemError(err.str()); throw SystemError(err.str());
} }
if( sender )
sender->askSensors(cmd);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void UNetExchange::sensorInfo( UniSetTypes::SensorMessage* sm ) void UNetExchange::sensorInfo( UniSetTypes::SensorMessage* sm )
{ {
if( sender ) if( sender )
sender->update(sm->id,sm->value); sender->updateSensor( sm->id , sm->value );
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
bool UNetExchange::activateObject() bool UNetExchange::activateObject()
...@@ -383,30 +396,53 @@ bool UNetExchange::activateObject() ...@@ -383,30 +396,53 @@ bool UNetExchange::activateObject()
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void UNetExchange::sigterm( int signo ) void UNetExchange::sigterm( int signo )
{ {
cerr << myname << ": ********* SIGTERM(" << signo <<") ********" << endl; dlog[Debug::INFO] << myname << ": ********* SIGTERM(" << signo <<") ********" << endl;
activated = false; activated = false;
for( ReceiverList::iterator it=recvlist.begin(); it!=recvlist.end(); ++it )
{
try
{
(*it)->stop();
}
catch(...){}
}
try
{
if( sender )
sender->stop();
}
catch(...){}
UniSetObject_LT::sigterm(signo); UniSetObject_LT::sigterm(signo);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void UNetExchange::initIterators() void UNetExchange::initIterators()
{ {
shm->initAIterator(aitHeartBeat); shm->initAIterator(aitHeartBeat);
if( sender )
sender->initIterators();
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetExchange::help_print( int argc, char* argv[] ) void UNetExchange::help_print( int argc, const char* argv[] )
{ {
cout << "--unet-recvpause msec - Пауза между получением пакетов. По умолчанию 10 мсек." << endl; cout << "--unet-name NameID - Идентификтора процесса." << endl;
cout << "--unet-updatepause msec - Пауза между обновлением данных в SM. По умолчанию 100 мсек." << endl; cout << "--unet-recv-timeout msec - Время для фиксации события 'отсутсвие связи'" << endl;
cout << "--unet-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl; cout << "--unet-lost-timeout msec - Время ожидания заполнения 'дырки' между пакетами. По умолчанию 5000 мсек." << endl;
cout << "--unet-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl; cout << "--unet-recvpause msec - Пауза между приёмами. По умолчанию 10" << endl;
cout << "--unet-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl; cout << "--unet-sendpause msec - Пауза между посылками. По умолчанию 150" << endl;
cout << "--unet-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl; cout << "--unet-updatepause msec - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--unet-notRespondSensor - датчик связи для данного процесса " << endl; cout << "--unet-steptime msec - Шаг..." << endl;
cout << "--unet-sm-ready-timeout - время на ожидание старта SM" << endl; cout << "--unet-maxdifferense num - Маскимальная разница в номерах пакетов для фиксации события 'потеря пакетов' " << endl;
cout << " Настройки протокола RS: " << endl; cout << "--unet-maxprocessingcount num - время на ожидание старта SM" << endl;
cout << "--unet-nosender [0,1] - Отключить посылку." << endl;
cout << "--unet-sm-ready-timeout msec - Время ожидание я готовности SM к работе. По умолчанию 15000" << endl;
cout << "--unet-filter-field name - Название фильтрующего поля при формировании списка датчиков посылаемых данным узлом" << endl;
cout << "--unet-filter-value name - Значение фильтрующего поля при формировании списка датчиков посылаемых данным узлом" << endl;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
UNetExchange* UNetExchange::init_unetexchange( int argc, char* argv[], UniSetTypes::ObjectId icID, SharedMemory* ic ) UNetExchange* UNetExchange::init_unetexchange( int argc, const char* argv[], UniSetTypes::ObjectId icID, SharedMemory* ic )
{ {
string name = conf->getArgParam("--unet-name","UNetExchange1"); string name = conf->getArgParam("--unet-name","UNetExchange1");
if( name.empty() ) if( name.empty() )
......
...@@ -14,6 +14,39 @@ ...@@ -14,6 +14,39 @@
#include "UNetReceiver.h" #include "UNetReceiver.h"
#include "UNetSender.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: class UNetExchange:
public UniSetObject_LT public UniSetObject_LT
{ {
...@@ -22,11 +55,11 @@ class UNetExchange: ...@@ -22,11 +55,11 @@ class UNetExchange:
virtual ~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 ); UniSetTypes::ObjectId shmID, SharedMemory* ic=0 );
/*! глобальная функция для вывода help-а */ /*! глобальная функция для вывода 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 ); bool checkExistUNetHost( const std::string host, ost::tpport_t port );
...@@ -53,7 +86,6 @@ class UNetExchange: ...@@ -53,7 +86,6 @@ class UNetExchange:
void initIterators(); void initIterators();
void startReceivers(); void startReceivers();
void initSender( const std::string host, const ost::tpport_t port, UniXML_iterator& it );
enum Timer enum Timer
{ {
......
...@@ -10,10 +10,10 @@ using namespace UniSetExtensions; ...@@ -10,10 +10,10 @@ using namespace UniSetExtensions;
bool UNetReceiver::PacketCompare::operator()(const UniSetUDP::UDPMessage& lhs, bool UNetReceiver::PacketCompare::operator()(const UniSetUDP::UDPMessage& lhs,
const UniSetUDP::UDPMessage& rhs) const const UniSetUDP::UDPMessage& rhs) const
{ {
// if( lhs.msg.header.num == rhs.msg.header.num ) // if( lhs.num == rhs.num )
// return (lhs.msg < rhs.msg); // return (lhs < rhs);
return lhs.msg.header.num > rhs.msg.header.num; return lhs.num > rhs.num;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
UNetReceiver::UNetReceiver( const std::string s_host, const ost::tpport_t port, SMInterface* smi ): UNetReceiver::UNetReceiver( const std::string s_host, const ost::tpport_t port, SMInterface* smi ):
...@@ -32,8 +32,10 @@ maxDifferens(1000), ...@@ -32,8 +32,10 @@ maxDifferens(1000),
waitClean(false), waitClean(false),
rnum(0), rnum(0),
maxProcessingCount(100), maxProcessingCount(100),
icache(200), d_icache(UniSetUDP::MaxDCount),
cache_init_ok(false) a_icache(UniSetUDP::MaxACount),
d_cache_init_ok(false),
a_cache_init_ok(false)
{ {
{ {
ostringstream s; ostringstream s;
...@@ -41,6 +43,7 @@ cache_init_ok(false) ...@@ -41,6 +43,7 @@ cache_init_ok(false)
myname = s.str(); myname = s.str();
} }
ost::Thread::setException(ost::Thread::throwException);
try try
{ {
// ost::IPV4Cidr ci(s_host.c_str()); // ost::IPV4Cidr ci(s_host.c_str());
...@@ -49,12 +52,18 @@ cache_init_ok(false) ...@@ -49,12 +52,18 @@ cache_init_ok(false)
addr = s_host.c_str(); addr = s_host.c_str();
udp = new ost::UDPDuplex(addr,port); udp = new ost::UDPDuplex(addr,port);
} }
catch( ost::SockException& e ) catch( std::exception& e )
{ {
ostringstream s; ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString(); s << myname << ": " << e.what();
dlog[Debug::CRIT] << myname << "(init): " << s.str() << std::endl; 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()); throw SystemError(s.str());
} }
...@@ -152,7 +161,7 @@ void UNetReceiver::real_update() ...@@ -152,7 +161,7 @@ void UNetReceiver::real_update()
return; return;
p = qpack.top(); p = qpack.top();
unsigned long sub = labs(p.msg.header.num - pnum); unsigned long sub = labs(p.num - pnum);
if( pnum > 0 ) if( pnum > 0 )
{ {
// если sub > maxDifferens // если sub > maxDifferens
...@@ -170,7 +179,7 @@ void UNetReceiver::real_update() ...@@ -170,7 +179,7 @@ void UNetReceiver::real_update()
lostPackets++; lostPackets++;
} }
else if( p.msg.header.num == pnum ) else if( p.num == pnum )
{ {
/* а что делать если идут повторные пакеты ?! /* а что делать если идут повторные пакеты ?!
* для надёжности лучше обрабатывать.. * для надёжности лучше обрабатывать..
...@@ -186,21 +195,63 @@ void UNetReceiver::real_update() ...@@ -186,21 +195,63 @@ void UNetReceiver::real_update()
// удаляем из очереди, только если // удаляем из очереди, только если
// всё в порядке с последовательностью.. // всё в порядке с последовательностью..
qpack.pop(); qpack.pop();
pnum = p.msg.header.num; pnum = p.num;
} // unlock qpack } // unlock qpack
k--; k--;
// cerr << myname << "(update): " << p.msg.header << endl; // cerr << myname << "(update): " << p.msg.header << endl;
initCache(p, !cache_init_ok); initDCache(p, !d_cache_init_ok);
initACache(p, !a_cache_init_ok);
// Обработка дискретных
size_t nbit = 0;
for( size_t i=0; i<p.dcount; i++, nbit++ )
{
try
{
long id = p.dID(i);
bool val = p.dValue(i);
ItemInfo& ii(d_icache[i]);
if( ii.id != id )
{
dlog[Debug::WARN] << myname << "(update): reinit cache for sid=" << id << endl;
ii.id = id;
shm->initAIterator(ii.ait);
shm->initDIterator(ii.dit);
}
if( ii.iotype == UniversalIO::DigitalInput )
shm->localSaveState(ii.dit,id,val,shm->ID());
else if( ii.iotype == UniversalIO::AnalogInput )
shm->localSaveValue(ii.ait,id,val,shm->ID());
else if( ii.iotype == UniversalIO::AnalogOutput )
shm->localSetValue(ii.ait,id,val,shm->ID());
else if( ii.iotype == UniversalIO::DigitalOutput )
shm->localSetState(ii.dit,id,val,shm->ID());
else
dlog[Debug::CRIT] << myname << "(update): Unknown iotype for sid=" << id << endl;
}
catch( UniSetTypes::Exception& ex)
{
dlog[Debug::CRIT] << myname << "(update): " << ex << std::endl;
}
catch(...)
{
dlog[Debug::CRIT] << myname << "(update): catch ..." << std::endl;
}
}
for( size_t i=0; i<p.msg.header.dcount; i++ ) // Обрабока аналоговых
for( size_t i=0; i<p.acount; i++ )
{ {
try try
{ {
UniSetUDP::UDPData& d = p.msg.dat[i]; UniSetUDP::UDPAData& d = p.a_dat[i];
ItemInfo& ii(icache[i]); ItemInfo& ii(a_icache[i]);
if( ii.id != d.id ) if( ii.id != d.id )
{ {
dlog[Debug::WARN] << myname << "(update): reinit cache for sid=" << d.id << endl; dlog[Debug::WARN] << myname << "(update): reinit cache for sid=" << d.id << endl;
...@@ -233,9 +284,17 @@ void UNetReceiver::real_update() ...@@ -233,9 +284,17 @@ void UNetReceiver::real_update()
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetReceiver::stop()
{
activated = false;
// msleep(10);
// u_thr->stop();
// r_thr->stop();
}
// -----------------------------------------------------------------------------
void UNetReceiver::receive() void UNetReceiver::receive()
{ {
cerr << "******************* receive start" << endl; dlog[Debug::INFO] << myname << ": ******************* receive start" << endl;
ptRecvTimeout.setTiming(recvTimeout); ptRecvTimeout.setTiming(recvTimeout);
while( activated ) while( activated )
{ {
...@@ -244,23 +303,23 @@ void UNetReceiver::receive() ...@@ -244,23 +303,23 @@ void UNetReceiver::receive()
if( recv() ) if( recv() )
ptRecvTimeout.reset(); ptRecvTimeout.reset();
} }
catch( ost::SockException& e ) catch( UniSetTypes::Exception& ex)
{ {
cerr << myname << "(receive): " << e.getString() << endl; dlog[Debug::WARN] << myname << "(receive): " << ex << std::endl;
} }
catch( UniSetTypes::Exception& ex) catch( std::exception& e )
{ {
cerr << myname << "(receive): " << ex << std::endl; dlog[Debug::WARN] << myname << "(receive): " << e.what()<< std::endl;
} }
catch(...) catch(...)
{ {
cerr << myname << "(preceive): catch ..." << std::endl; dlog[Debug::WARN] << myname << "(receive): catch ..." << std::endl;
} }
msleep(recvpause); msleep(recvpause);
} }
cerr << "************* execute FINISH **********" << endl; dlog[Debug::INFO] << myname << ": ************* receive FINISH **********" << endl;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool UNetReceiver::recv() bool UNetReceiver::recv()
...@@ -268,23 +327,16 @@ bool UNetReceiver::recv() ...@@ -268,23 +327,16 @@ bool UNetReceiver::recv()
if( !udp->isInputReady(recvTimeout) ) if( !udp->isInputReady(recvTimeout) )
return false; return false;
size_t ret = udp->UDPReceive::receive(&(pack.msg),sizeof(pack.msg)); size_t ret = udp->UDPReceive::receive((char*)(&r_buf),sizeof(r_buf));
if( ret < sizeof(UniSetUDP::UDPHeader) )
{
dlog[Debug::CRIT] << myname << "(receive): FAILED header ret=" << ret << " sizeof=" << sizeof(UniSetUDP::UDPHeader) << endl;
return false;
}
size_t sz = pack.msg.header.dcount * sizeof(UniSetUDP::UDPData) + sizeof(UniSetUDP::UDPHeader); size_t sz = UniSetUDP::UDPMessage::getMessage(pack,r_buf);
if( ret < sz ) if( sz == 0 )
{ {
dlog[Debug::CRIT] << myname << "(receive): FAILED data ret=" << ret << " sizeof=" << sz dlog[Debug::CRIT] << myname << "(receive): FAILED RECEIVE DATA ret=" << ret << endl;
<< " packnum=" << pack.msg.header.num << endl;
return false; return false;
} }
if( rnum>0 && labs(pack.num - rnum) > maxDifferens )
if( rnum>0 && labs(pack.msg.header.num - rnum) > maxDifferens )
{ {
/* А что делать если мы уже ждём и ещё не "разгребли предыдущее".. а тут уже повторный "разрыв" /* А что делать если мы уже ждём и ещё не "разгребли предыдущее".. а тут уже повторный "разрыв"
* Можно откинуть всё.. что сложили во временную очередь и заново "копить" (но тогда теряем информацию) * Можно откинуть всё.. что сложили во временную очередь и заново "копить" (но тогда теряем информацию)
...@@ -303,12 +355,19 @@ bool UNetReceiver::recv() ...@@ -303,12 +355,19 @@ bool UNetReceiver::recv()
waitClean = true; waitClean = true;
} }
rnum = pack.msg.header.num; rnum = pack.num;
// cerr << myname << "(receive): recv DATA OK. ret=" << ret << " sizeof=" << sz #if 0
// << " header: " << pack.msg.header cerr << myname << "(receive): recv DATA OK. ret=" << ret << " sizeof=" << sz
// << " waitClean=" << waitClean << " header: " << pack.msg.header
// << endl; << " waitClean=" << waitClean
<< endl;
for( size_t i=0; i<pack.msg.header.dcount; i++ )
{
UniSetUDP::UDPData& d = pack.msg.dat[i];
cerr << "****** save id=" << d.id << " val=" << d.val << endl;
}
#endif
{ // lock qpack { // lock qpack
uniset_mutex_lock l(packMutex,500); uniset_mutex_lock l(packMutex,500);
...@@ -347,28 +406,56 @@ bool UNetReceiver::recv() ...@@ -347,28 +406,56 @@ bool UNetReceiver::recv()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetReceiver::initIterators() void UNetReceiver::initIterators()
{ {
for( ItemVec::iterator it=icache.begin(); it!=icache.end(); ++it ) for( ItemVec::iterator it=d_icache.begin(); it!=d_icache.end(); ++it )
{
shm->initAIterator(it->ait);
shm->initDIterator(it->dit);
}
for( ItemVec::iterator it=a_icache.begin(); it!=a_icache.end(); ++it )
{ {
shm->initAIterator(it->ait); shm->initAIterator(it->ait);
shm->initDIterator(it->dit); shm->initDIterator(it->dit);
} }
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetReceiver::initCache( UniSetUDP::UDPMessage& pack, bool force ) void UNetReceiver::initDCache( UniSetUDP::UDPMessage& pack, bool force )
{
if( !force && pack.dcount == d_icache.size() )
return;
dlog[Debug::INFO] << myname << ": init icache.." << endl;
d_cache_init_ok = true;
d_icache.resize(pack.dcount);
for( size_t i=0; i<d_icache.size(); i++ )
{
ItemInfo& d(d_icache[i]);
if( d.id != pack.d_id[i] )
{
d.id = pack.d_id[i];
d.iotype = conf->getIOType(d.id);
shm->initAIterator(d.ait);
shm->initDIterator(d.dit);
}
}
}
// -----------------------------------------------------------------------------
void UNetReceiver::initACache( UniSetUDP::UDPMessage& pack, bool force )
{ {
if( !force && pack.msg.header.dcount == icache.size() ) if( !force && pack.acount == a_icache.size() )
return; return;
dlog[Debug::INFO] << myname << ": init icache.." << endl; dlog[Debug::INFO] << myname << ": init icache.." << endl;
cache_init_ok = true; a_cache_init_ok = true;
icache.resize(pack.msg.header.dcount); a_icache.resize(pack.acount);
for( size_t i=0; i<icache.size(); i++ ) for( size_t i=0; i<a_icache.size(); i++ )
{ {
ItemInfo& d(icache[i]); ItemInfo& d(a_icache[i]);
if( d.id != pack.msg.dat[i].id ) if( d.id != pack.a_dat[i].id )
{ {
d.id = pack.msg.dat[i].id; d.id = pack.a_dat[i].id;
d.iotype = conf->getIOType(d.id); d.iotype = conf->getIOType(d.id);
shm->initAIterator(d.ait); shm->initAIterator(d.ait);
shm->initDIterator(d.dit); shm->initDIterator(d.dit);
......
...@@ -53,6 +53,7 @@ class UNetReceiver ...@@ -53,6 +53,7 @@ class UNetReceiver
~UNetReceiver(); ~UNetReceiver();
void start(); void start();
void stop();
void receive(); void receive();
void update(); void update();
...@@ -114,6 +115,7 @@ class UNetReceiver ...@@ -114,6 +115,7 @@ class UNetReceiver
typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue; typedef std::priority_queue<UniSetUDP::UDPMessage,std::vector<UniSetUDP::UDPMessage>,PacketCompare> PacketQueue;
PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */ PacketQueue qpack; /*!< очередь принятых пакетов (отсортированных по возрастанию номера пакета) */
UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очереlного сообщения */ UniSetUDP::UDPMessage pack; /*!< просто буфер для получения очереlного сообщения */
UniSetUDP::UDPPacket r_buf;
UniSetTypes::uniset_mutex packMutex; /*!< mutex для работы с очередью */ UniSetTypes::uniset_mutex packMutex; /*!< mutex для работы с очередью */
unsigned long pnum; /*!< текущий номер обработанного сообщения, для проверки непрерывности последовательности пакетов */ unsigned long pnum; /*!< текущий номер обработанного сообщения, для проверки непрерывности последовательности пакетов */
...@@ -134,13 +136,21 @@ class UNetReceiver ...@@ -134,13 +136,21 @@ class UNetReceiver
IOController::AIOStateList::iterator ait; IOController::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit; IOController::DIOStateList::iterator dit;
UniversalIO::IOTypes iotype; UniversalIO::IOTypes iotype;
ItemInfo():
id(UniSetTypes::DefaultObjectId),
iotype(UniversalIO::UnknownIOType){}
}; };
typedef std::vector<ItemInfo> ItemVec; typedef std::vector<ItemInfo> ItemVec;
ItemVec icache; /*!< кэш итераторов */ ItemVec d_icache; /*!< кэш итераторов для булевых */
bool cache_init_ok; ItemVec a_icache; /*!< кэш итераторов для аналоговых */
void initCache( UniSetUDP::UDPMessage& pack, bool force=false );
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_ #endif // UNetReceiver_H_
......
...@@ -36,16 +36,24 @@ s_thr(0) ...@@ -36,16 +36,24 @@ s_thr(0)
if( dlog.debugging(Debug::INFO) ) if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(UNetSender): UDP set to " << s_host << ":" << port << endl; dlog[Debug::INFO] << "(UNetSender): UDP set to " << s_host << ":" << port << endl;
ost::Thread::setException(ost::Thread::throwException);
try try
{ {
addr = s_host.c_str(); addr = s_host.c_str();
udp = new ost::UDPBroadcast(addr,port); udp = new ost::UDPBroadcast(addr,port);
} }
catch( ost::SockException& e ) catch( std::exception& e )
{
ostringstream s;
s << myname << ": " << e.what();
dlog[Debug::CRIT] << s.str() << std::endl;
throw SystemError(s.str());
}
catch( ... )
{ {
ostringstream s; ostringstream s;
s << e.getString() << ": " << e.getSystemErrorString() << endl; s << myname << ": catch...";
dlog[Debug::CRIT] << s.str() << std::endl;
throw SystemError(s.str()); throw SystemError(s.str());
} }
...@@ -63,8 +71,8 @@ s_thr(0) ...@@ -63,8 +71,8 @@ s_thr(0)
// выставляем поля, которые не меняются // выставляем поля, которые не меняются
mypack.msg.header.nodeID = conf->getLocalNode(); mypack.nodeID = conf->getLocalNode();
mypack.msg.header.procID = shm->ID(); mypack.procID = shm->ID();
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
UNetSender::~UNetSender() UNetSender::~UNetSender()
...@@ -74,18 +82,56 @@ UNetSender::~UNetSender() ...@@ -74,18 +82,56 @@ UNetSender::~UNetSender()
delete shm; delete shm;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetSender::update( UniSetTypes::ObjectId id, long value ) void UNetSender::updateFromSM()
{ {
DMap::iterator it=dlist.begin(); DMap::iterator it=dlist.begin();
for( ; it!=dlist.end(); ++it ) 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); dlog[Debug::CRIT] << myname << "(update): Unknown iotype for sid=" << it->id << endl;
it->val = value; continue;
} }
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; 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);
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetSender::send() void UNetSender::send()
...@@ -110,42 +156,56 @@ void UNetSender::send() ...@@ -110,42 +156,56 @@ void UNetSender::send()
{ {
try try
{ {
if( !shm->isLocalwork() )
updateFromSM();
real_send(); real_send();
} }
catch( ost::SockException& e ) catch( ost::SockException& e )
{ {
cerr << myname << "(send): " << e.getString() << endl; dlog[Debug::WARN] << myname << "(send): " << e.getString() << endl;
} }
catch( UniSetTypes::Exception& ex) 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(...) catch(...)
{ {
cerr << myname << "(send): catch ..." << std::endl; dlog[Debug::WARN] << myname << "(send): catch ..." << std::endl;
} }
msleep(sendpause); msleep(sendpause);
} }
cerr << "************* execute FINISH **********" << endl; dlog[Debug::INFO] << "************* execute FINISH **********" << endl;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetSender::real_send() void UNetSender::real_send()
{ {
mypack.msg.header.num = packetnum++; UniSetTypes::uniset_mutex_lock l(pack_mutex,300);
mypack.num = packetnum++;
if( packetnum > UniSetUDP::MaxPacketNum ) if( packetnum > UniSetUDP::MaxPacketNum )
packetnum = 1; packetnum = 1;
// cout << "************* send header: " << mypack.msg.header << endl;
size_t sz = mypack.byte_size() + sizeof(UniSetUDP::UDPHeader);
if( !udp->isPending(ost::Socket::pendingOutput) ) if( !udp->isPending(ost::Socket::pendingOutput) )
return; return;
size_t ret = udp->send( (char*)&(mypack.msg),sz);
if( ret < sz ) mypack.transport_msg(s_msg);
dlog[Debug::CRIT] << myname << "(real_send): FAILED ret=" << ret << " < sizeof=" << sz << endl; 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() void UNetSender::start()
...@@ -208,7 +268,7 @@ bool UNetSender::initItem( UniXML_iterator& it ) ...@@ -208,7 +268,7 @@ bool UNetSender::initItem( UniXML_iterator& it )
{ {
string sname( it.getProp("name") ); string sname( it.getProp("name") );
string tid = it.getProp("id"); string tid(it.getProp("id"));
ObjectId sid; ObjectId sid;
if( !tid.empty() ) if( !tid.empty() )
...@@ -229,12 +289,40 @@ bool UNetSender::initItem( UniXML_iterator& it ) ...@@ -229,12 +289,40 @@ bool UNetSender::initItem( UniXML_iterator& it )
} }
UItem p; UItem p;
p.si.id = sid; p.iotype = UniSetTypes::getIOType(it.getProp("iotype"));
p.si.node = conf->getLocalNode();
mypack.addData(sid,0); if( p.iotype == UniversalIO::UnknownIOType )
p.pack_ind = mypack.size()-1; {
dlog[Debug::CRIT] << myname << "(readItem): Unknown iotype for sid=" << sid << endl;
return false;
}
p.id = sid;
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 >= mypack.size() ) if( maxItem >= dlist.size() )
dlist.resize(maxItem+10); dlist.resize(maxItem+10);
dlist[maxItem] = p; dlist[maxItem] = p;
...@@ -247,6 +335,11 @@ bool UNetSender::initItem( UniXML_iterator& it ) ...@@ -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() void UNetSender::initIterators()
{ {
DMap::iterator it=dlist.begin(); DMap::iterator it=dlist.begin();
...@@ -257,8 +350,10 @@ void UNetSender::initIterators() ...@@ -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 ...@@ -29,27 +29,44 @@ class UNetSender
struct UItem struct UItem
{ {
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::AIOStateList::iterator ait;
IOController::DIOStateList::iterator dit; IOController::DIOStateList::iterator dit;
UniSetTypes::uniset_spin_mutex val_lock;
int pack_ind; int pack_ind;
long val;
friend std::ostream& operator<<( std::ostream& os, UItem& p ); friend std::ostream& operator<<( std::ostream& os, UItem& p );
}; };
typedef std::vector<UItem> DMap;
void start(); void start();
void stop();
void send(); void send();
void real_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; } inline void setSendPause( int msec ){ sendpause = msec; }
/*! заказать датчики */
void askSensors( UniversalIO::UIOCommand cmd );
/*! инициализация итераторов */
void initIterators();
protected: protected:
std::string s_field; std::string s_field;
...@@ -57,7 +74,6 @@ class UNetSender ...@@ -57,7 +74,6 @@ class UNetSender
SMInterface* shm; SMInterface* shm;
void initIterators();
bool initItem( UniXML_iterator& it ); bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec ); bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
...@@ -76,11 +92,12 @@ class UNetSender ...@@ -76,11 +92,12 @@ class UNetSender
int sendpause; int sendpause;
bool activated; bool activated;
UniSetTypes::uniset_mutex pack_mutex;
UniSetUDP::UDPMessage mypack; UniSetUDP::UDPMessage mypack;
typedef std::vector<UItem> DMap;
DMap dlist; DMap dlist;
int maxItem; int maxItem;
unsigned long packetnum; unsigned long packetnum;
UniSetUDP::UDPPacket s_msg;
ThreadCreator<UNetSender>* s_thr; // send thread 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 <sstream>
#include <sys/wait.h>
#include "ObjectsActivator.h" #include "ObjectsActivator.h"
#include "Extensions.h" #include "Extensions.h"
#include "UNetExchange.h" #include "UNetExchange.h"
...@@ -7,7 +8,7 @@ using namespace std; ...@@ -7,7 +8,7 @@ using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
using namespace UniSetExtensions; using namespace UniSetExtensions;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
int main( int argc, char** argv ) int main( int argc, const char** argv )
{ {
try try
{ {
...@@ -21,20 +22,19 @@ int main( int argc, char** argv ) ...@@ -21,20 +22,19 @@ int main( int argc, char** argv )
return 0; return 0;
} }
string confile=UniSetTypes::getArgParam("--confile",argc,argv,"configure.xml"); uniset_init(argc,argv);
conf = new Configuration( argc, argv, confile );
string logfilename(conf->getArgParam("--unet-logfile")); string logfilename(conf->getArgParam("--unet-logfile"));
if( logfilename.empty() ) if( logfilename.empty() )
logfilename = "udpexchange.log"; logfilename = "udpexchange.log";
conf->initDebug(dlog,"dlog");
std::ostringstream logname; std::ostringstream logname;
string dir(conf->getLogDir()); string dir(conf->getLogDir());
logname << dir << logfilename; logname << dir << logfilename;
unideb.logFile( logname.str() ); unideb.logFile( logname.str() );
dlog.logFile( logname.str() ); UniSetExtensions::dlog.logFile( logname.str() );
conf->initDebug(UniSetExtensions::dlog,"dlog");
ObjectId shmID = DefaultObjectId; ObjectId shmID = DefaultObjectId;
string sID = conf->getArgParam("--smemory-id"); string sID = conf->getArgParam("--smemory-id");
...@@ -68,21 +68,17 @@ int main( int argc, char** argv ) ...@@ -68,21 +68,17 @@ int main( int argc, char** argv )
dlog[Debug::ANY] << "(main): -------------- UDPReceiver START -------------------------\n\n"; dlog[Debug::ANY] << "(main): -------------- UDPReceiver START -------------------------\n\n";
act.run(false); act.run(false);
while( waitpid(-1, 0, 0) > 0 );
} }
catch( Exception& ex ) catch( Exception& ex )
{ {
dlog[Debug::CRIT] << "(unetexchange): " << ex << std::endl; 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(...) catch(...)
{ {
dlog[Debug::CRIT] << "(unetexchange): catch ..." << std::endl; dlog[Debug::CRIT] << "(unetexchange): catch ..." << std::endl;
} }
while( waitpid(-1, 0, 0) > 0 );
return 0; return 0;
} }
...@@ -9,6 +9,29 @@ ...@@ -9,6 +9,29 @@
#include "SharedMemory.h" #include "SharedMemory.h"
#include "PassiveTimer.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: class UniExchange:
public IOController public IOController
{ {
......
#include <sys/wait.h>
#include <string> #include <string>
#include "Debug.h" #include "Debug.h"
#include "ObjectsActivator.h" #include "ObjectsActivator.h"
...@@ -52,6 +53,7 @@ int main(int argc, const char **argv) ...@@ -52,6 +53,7 @@ int main(int argc, const char **argv)
act.broadcast( sm.transport_msg() ); act.broadcast( sm.transport_msg() );
act.run(true); act.run(true);
shm->execute(); shm->execute();
while( waitpid(-1, 0, 0) > 0 );
return 0; return 0;
} }
catch(SystemError& err) catch(SystemError& err)
...@@ -67,5 +69,6 @@ int main(int argc, const char **argv) ...@@ -67,5 +69,6 @@ int main(int argc, const char **argv)
unideb[Debug::CRIT] << "(uninetwork): catch(...)" << endl; unideb[Debug::CRIT] << "(uninetwork): catch(...)" << endl;
} }
while( waitpid(-1, 0, 0) > 0 );
return 1; 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 ...@@ -71,6 +71,7 @@ class UniversalInterface
~UniversalInterface(); ~UniversalInterface();
inline UniSetTypes::ObjectIndex* getObjectIndex() { return oind; } inline UniSetTypes::ObjectIndex* getObjectIndex() { return oind; }
inline UniSetTypes::Configuration* getConf() { return uconf; }
// -------- Функции работы с группой датчиков ----------- // -------- Функции работы с группой датчиков -----------
......
...@@ -127,6 +127,9 @@ class ModbusClient ...@@ -127,6 +127,9 @@ class ModbusClient
*/ */
int setAfterSendPause( timeout_t msec ); 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 initLog( UniSetTypes::Configuration* conf, const std::string name, const std::string logfile="" );
void setLog( DebugStream& dlog ); void setLog( DebugStream& dlog );
...@@ -173,6 +176,7 @@ class ModbusClient ...@@ -173,6 +176,7 @@ class ModbusClient
timeout_t replyTimeOut_ms; /*!< таймаут на ожидание ответа */ timeout_t replyTimeOut_ms; /*!< таймаут на ожидание ответа */
timeout_t aftersend_msec; /*!< пауза после посылки запроса */ timeout_t aftersend_msec; /*!< пауза после посылки запроса */
timeout_t sleepPause_usec; /*!< пауза между попытками чтения символа из канала */
bool crcNoCheckit; bool crcNoCheckit;
...@@ -182,6 +186,8 @@ class ModbusClient ...@@ -182,6 +186,8 @@ class ModbusClient
void printProcessingTime(); void printProcessingTime();
PassiveTimer tmProcessing; PassiveTimer tmProcessing;
private: private:
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
......
...@@ -42,6 +42,9 @@ class ModbusServer ...@@ -42,6 +42,9 @@ class ModbusServer
/*! установить время ожидания по умолчанию */ /*! установить время ожидания по умолчанию */
void setRecvTimeout( timeout_t msec ); void setRecvTimeout( timeout_t msec );
/*! установить паузу при ожидании символа */
inline void setSleepPause( timeout_t usec ){ sleepPause_usec = usec; }
inline void setCRCNoCheckit( bool set ){ crcNoCheckit = set; } inline void setCRCNoCheckit( bool set ){ crcNoCheckit = set; }
inline bool isCRCNoCheckit(){ return crcNoCheckit; } inline bool isCRCNoCheckit(){ return crcNoCheckit; }
...@@ -203,6 +206,7 @@ class ModbusServer ...@@ -203,6 +206,7 @@ class ModbusServer
timeout_t recvTimeOut_ms; /*!< таймаут на приём */ timeout_t recvTimeOut_ms; /*!< таймаут на приём */
timeout_t replyTimeout_ms; /*!< таймаут на формирование ответа */ timeout_t replyTimeout_ms; /*!< таймаут на формирование ответа */
timeout_t aftersend_msec; /*!< пауза после посылки ответа */ timeout_t aftersend_msec; /*!< пауза после посылки ответа */
timeout_t sleepPause_usec; /*!< пауза между попытками чтения символа из канала */
bool onBroadcast; /*!< включен режим работы с broadcst-сообщениями */ bool onBroadcast; /*!< включен режим работы с broadcst-сообщениями */
bool crcNoCheckit; bool crcNoCheckit;
......
...@@ -13,6 +13,7 @@ using namespace UniSetTypes; ...@@ -13,6 +13,7 @@ using namespace UniSetTypes;
ModbusClient::ModbusClient(): ModbusClient::ModbusClient():
replyTimeOut_ms(2000), replyTimeOut_ms(2000),
aftersend_msec(0), aftersend_msec(0),
sleepPause_usec(100),
crcNoCheckit(false) crcNoCheckit(false)
{ {
tmProcessing.setTiming(replyTimeOut_ms); tmProcessing.setTiming(replyTimeOut_ms);
...@@ -288,11 +289,13 @@ mbErrCode ModbusClient::recv( ModbusAddr addr, ModbusByte qfunc, ...@@ -288,11 +289,13 @@ mbErrCode ModbusClient::recv( ModbusAddr addr, ModbusByte qfunc,
while( !tmAbort.checkTime() ) while( !tmAbort.checkTime() )
{ {
bcnt = getNextData((unsigned char*)(&rbuf),sizeof(ModbusAddr)); bcnt = getNextData((unsigned char*)(&rbuf),sizeof(ModbusAddr));
if( bcnt!=0 && ( rbuf.addr==addr ) ) // || (onBroadcast && rbuf.addr==BroadcastAddr) ) ) if( bcnt>0 && ( rbuf.addr==addr ) ) // || (onBroadcast && rbuf.addr==BroadcastAddr) ) )
{ {
begin = true; begin = true;
break; break;
} }
usleep(sleepPause_usec);
} }
if( !begin ) if( !begin )
......
...@@ -15,6 +15,7 @@ ModbusServer::ModbusServer(): ...@@ -15,6 +15,7 @@ ModbusServer::ModbusServer():
recvTimeOut_ms(50), recvTimeOut_ms(50),
replyTimeout_ms(2000), replyTimeout_ms(2000),
aftersend_msec(0), aftersend_msec(0),
sleepPause_usec(100),
onBroadcast(false), onBroadcast(false),
crcNoCheckit(false) crcNoCheckit(false)
{ {
...@@ -472,6 +473,8 @@ mbErrCode ModbusServer::recv( ModbusRTU::ModbusAddr addr, ModbusMessage& rbuf, t ...@@ -472,6 +473,8 @@ mbErrCode ModbusServer::recv( ModbusRTU::ModbusAddr addr, ModbusMessage& rbuf, t
begin = true; begin = true;
break; break;
} }
usleep(sleepPause_usec);
} }
if( !begin ) if( !begin )
......
...@@ -17,6 +17,11 @@ iaddr(""), ...@@ -17,6 +17,11 @@ iaddr(""),
force_disconnect(true) force_disconnect(true)
{ {
setCRCNoCheckit(true); setCRCNoCheckit(true);
/*
dlog.addLevel(Debug::INFO);
dlog.addLevel(Debug::WARN);
dlog.addLevel(Debug::CRIT);
*/
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -187,8 +192,9 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg, ...@@ -187,8 +192,9 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
} }
// //
// return recv(addr,msg.func,reply,timeout); // timeout = ptTimeout.getLeft(timeout);
mbErrCode res = recv(addr,msg.func,reply,timeout); // в tcp ответе задержек уже не должно быть..
mbErrCode res = recv(addr,msg.func,reply,1); //timeout);
if( force_disconnect ) if( force_disconnect )
{ {
...@@ -232,6 +238,11 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg, ...@@ -232,6 +238,11 @@ mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
dlog[Debug::WARN] << "(query): tcp error: " << e.getString() << endl; dlog[Debug::WARN] << "(query): tcp error: " << e.getString() << endl;
return erTimeOut; return erTimeOut;
} }
catch( std::exception& e )
{
dlog[Debug::CRIT] << "(query): " << e.what() << std::endl;
return erTimeOut;
}
catch(...) catch(...)
{ {
dlog[Debug::WARN] << "(query): cath..." << endl; dlog[Debug::WARN] << "(query): cath..." << endl;
...@@ -264,7 +275,7 @@ void ModbusTCPMaster::reconnect() ...@@ -264,7 +275,7 @@ void ModbusTCPMaster::reconnect()
tcp = 0; tcp = 0;
} }
ost::Thread::setException(ost::Thread::throwException); // ost::Thread::setException(ost::Thread::throwException);
try try
{ {
...@@ -272,20 +283,17 @@ void ModbusTCPMaster::reconnect() ...@@ -272,20 +283,17 @@ void ModbusTCPMaster::reconnect()
tcp = new ost::TCPStream(iaddr.c_str(),ost::Socket::IPV4,536,true,500); tcp = new ost::TCPStream(iaddr.c_str(),ost::Socket::IPV4,536,true,500);
tcp->setTimeout(replyTimeOut_ms); tcp->setTimeout(replyTimeOut_ms);
} }
catch(ost::Socket *socket) catch( std::exception& e )
{ {
ost::tpport_t port; ostringstream s;
int err = socket->getErrorNumber(); s << "(ModbusTCPMaster): connection " << s.str() << " error: " << e.what();
ost::InetAddress saddr = (ost::InetAddress)socket->getPeer(&port); dlog[Debug::CRIT] << s.str() << std::endl;
dlog[Debug::CRIT] << "tcp error " << saddr.getHostname() << ":" << port << " = " << err << endl;
}
catch( ost::SockException& e)
{
dlog[Debug::CRIT] << "tcp error: " << e.getString() << endl;
} }
catch(...) catch( ... )
{ {
dlog[Debug::CRIT] << "create TCPStream[" << iaddr << "] error..." << endl; ostringstream s;
s << "(ModbusTCPMaster): connection " << s.str() << " error: catch ...";
dlog[Debug::CRIT] << s.str() << std::endl;
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -307,25 +315,24 @@ void ModbusTCPMaster::connect( ost::InetAddress addr, int port ) ...@@ -307,25 +315,24 @@ void ModbusTCPMaster::connect( ost::InetAddress addr, int port )
dlog[Debug::INFO] << "(ModbusTCPMaster): connect to " << s.str() << endl; dlog[Debug::INFO] << "(ModbusTCPMaster): connect to " << s.str() << endl;
iaddr = s.str(); iaddr = s.str();
ost::Thread::setException(ost::Thread::throwException);
try try
{ {
tcp = new ost::TCPStream(iaddr.c_str()); tcp = new ost::TCPStream(iaddr.c_str());
tcp->setTimeout(replyTimeOut_ms); tcp->setTimeout(replyTimeOut_ms);
} }
catch(ost::Socket *socket) catch( std::exception& e )
{
ost::tpport_t port;
int err = socket->getErrorNumber();
ost::InetAddress saddr = (ost::InetAddress)socket->getPeer(&port);
dlog[Debug::CRIT] << ": tcp error " << saddr.getHostname() << ":" << port << " = " << err << endl;
}
catch( ost::SockException& e)
{ {
dlog[Debug::CRIT] << "tcp error: " << e.getString() << endl; ostringstream s;
s << "(ModbusTCPMaster): connection " << s.str() << " error: " << e.what();
dlog[Debug::CRIT] << s.str() << std::endl;
} }
catch(...) catch( ... )
{ {
dlog[Debug::CRIT] << "create TCPStream[" << iaddr << "] error..." << endl; ostringstream s;
s << "(ModbusTCPMaster): connection " << s.str() << " error: catch ...";
dlog[Debug::CRIT] << s.str() << std::endl;
} }
// } // }
} }
......
...@@ -83,11 +83,18 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou ...@@ -83,11 +83,18 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou
addr = _addr; addr = _addr;
else if( _addr != addr ) else if( _addr != addr )
{ {
res = erTimeOut;
// На такие запросы просто не отвечаем...
/*
res = erBadReplyNodeAddress;
tmProcessing.setTiming(replyTimeout_ms); tmProcessing.setTiming(replyTimeout_ms);
ErrorRetMessage em( buf.addr, buf.func, erBadReplyNodeAddress ); ErrorRetMessage em( _addr, buf.func, res );
buf = em.transport_msg(); buf = em.transport_msg();
send(buf); send(buf);
printProcessingTime(); printProcessingTime();
if( aftersend_msec >= 0 )
msleep(aftersend_msec);
*/
tcp.disconnect(); tcp.disconnect();
return res; return res;
} }
...@@ -99,7 +106,7 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou ...@@ -99,7 +106,7 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou
{ {
if( res < erInternalErrorCode ) if( res < erInternalErrorCode )
{ {
ErrorRetMessage em( buf.addr, buf.func, res ); ErrorRetMessage em( addr, buf.func, res );
buf = em.transport_msg(); buf = em.transport_msg();
send(buf); send(buf);
printProcessingTime(); printProcessingTime();
...@@ -135,9 +142,9 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou ...@@ -135,9 +142,9 @@ mbErrCode ModbusTCPServer::receive( ModbusRTU::ModbusAddr addr, timeout_t timeou
tcp.disconnect(); tcp.disconnect();
} }
} }
catch( ost::SockException& e ) catch( ost::Exception& e )
{ {
cout << e.getString() << ": " << e.getSystemErrorString() << endl; cout << "(ModbusTCPServer): " << e.what() << endl;
return erInternalErrorCode; return erInternalErrorCode;
} }
......
...@@ -199,7 +199,8 @@ void IONotifyController::askState( const IOController_i::SensorInfo& si, ...@@ -199,7 +199,8 @@ void IONotifyController::askState( const IOController_i::SensorInfo& si,
// контроль заказа типа датчика(дискретного) здесь производится // контроль заказа типа датчика(дискретного) здесь производится
if( unideb.debugging(Debug::INFO) ) if( unideb.debugging(Debug::INFO) )
{ {
unideb[Debug::INFO] << "поступил заказ от " unideb[Debug::INFO] << "(askState): поступил " << ( cmd == UIODontNotify ? "отказ" :"заказ" )
<< " от "
<< conf->oind->getNameById(ci.id, ci.node) << " на дискретный датчик " << conf->oind->getNameById(ci.id, ci.node) << " на дискретный датчик "
<< conf->oind->getNameById(si.id,si.node) << endl; << conf->oind->getNameById(si.id,si.node) << endl;
} }
...@@ -284,7 +285,8 @@ void IONotifyController::askValue(const IOController_i::SensorInfo& si, ...@@ -284,7 +285,8 @@ void IONotifyController::askValue(const IOController_i::SensorInfo& si,
if( unideb.debugging(Debug::INFO) ) if( unideb.debugging(Debug::INFO) )
{ {
unideb[Debug::INFO] << "поступил заказ от "<< conf->oind->getNameById(ci.id, ci.node) unideb[Debug::INFO] << "(askValue): поступил " << ( cmd == UIODontNotify ? "отказ" :"заказ" ) << " от "
<< conf->oind->getNameById(ci.id, ci.node)
<< " на аналоговый датчик " << " на аналоговый датчик "
<< conf->oind->getNameById(si.id,si.node) << endl; << conf->oind->getNameById(si.id,si.node) << endl;
} }
...@@ -1082,7 +1084,8 @@ void IONotifyController::askOutput(const IOController_i::SensorInfo& si, ...@@ -1082,7 +1084,8 @@ void IONotifyController::askOutput(const IOController_i::SensorInfo& si,
string name = conf->oind->getNameById(ci.id, ci.node); string name = conf->oind->getNameById(ci.id, ci.node);
if( unideb.debugging(Debug::INFO) ) if( unideb.debugging(Debug::INFO) )
{ {
unideb[Debug::INFO] << "(askOutput): поступил заказ от ("<< ci.id << ") " unideb[Debug::INFO] << "(askOutput): поступил " << ( cmd == UIODontNotify ? "отказ" :"заказ" )
<< " от ("<< ci.id << ") "
<< name << " на выход " << name << " на выход "
<< conf->oind->getNameById(si.id,si.node) << endl; << conf->oind->getNameById(si.id,si.node) << endl;
} }
......
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