Commit 12eba23d authored by Pavel Vainerman's avatar Pavel Vainerman

backported to p8 as 2.8-alt7.M80P.8 (with rpmbph script)

parents 1a3f2de4 026e2664
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <getopt.h> #include <getopt.h>
#include <chrono>
#include "Debug.h" #include "Debug.h"
#include "modbus/ModbusRTUMaster.h" #include "modbus/ModbusRTUMaster.h"
#include "modbus/ModbusHelpers.h" #include "modbus/ModbusHelpers.h"
...@@ -96,7 +97,22 @@ enum Command ...@@ -96,7 +97,22 @@ enum Command
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static char* checkArg( int ind, int argc, char* argv[] ); static char* checkArg( int ind, int argc, char* argv[] );
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
struct Interval
{
using time_point = std::chrono::time_point<std::chrono::steady_clock>;
Interval()
:tmStart(std::chrono::steady_clock::now())
{}
uint64_t microseconds()
{
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - tmStart).count();
}
time_point tmStart;
};
// --------------------------------------------------------------------------
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
// std::ios::sync_with_stdio(false); // std::ios::sync_with_stdio(false);
...@@ -413,7 +429,6 @@ int main( int argc, char** argv ) ...@@ -413,7 +429,6 @@ int main( int argc, char** argv )
{ {
try try
{ {
switch(cmd) switch(cmd)
{ {
case cmdRead01: case cmdRead01:
...@@ -426,12 +441,15 @@ int main( int argc, char** argv ) ...@@ -426,12 +441,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::ReadCoilRetMessage ret = mb.read01(slaveaddr, reg, count); ModbusRTU::ReadCoilRetMessage ret = mb.read01(slaveaddr, reg, count);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << (int)ret.bcnt << endl; cout << "(reply): count=" << (int)ret.bcnt
<< " [" << i.microseconds() << " ms]"
<< endl;
for( int i = 0; i < ret.bcnt; i++ ) for( int i = 0; i < ret.bcnt; i++ )
{ {
...@@ -453,12 +471,15 @@ int main( int argc, char** argv ) ...@@ -453,12 +471,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::ReadInputStatusRetMessage ret = mb.read02(slaveaddr, reg, count); ModbusRTU::ReadInputStatusRetMessage ret = mb.read02(slaveaddr, reg, count);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << (int)ret.bcnt << endl; cout << "(reply): count=" << (int)ret.bcnt
<< " [" << i.microseconds() << " ms]"
<< endl;
for( int i = 0; i < ret.bcnt; i++ ) for( int i = 0; i < ret.bcnt; i++ )
{ {
...@@ -480,12 +501,15 @@ int main( int argc, char** argv ) ...@@ -480,12 +501,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::ReadOutputRetMessage ret = mb.read03(slaveaddr, reg, count); ModbusRTU::ReadOutputRetMessage ret = mb.read03(slaveaddr, reg, count);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << ModbusRTU::dat2str(ret.count) << endl; cout << "(reply): count=" << ModbusRTU::dat2str(ret.count)
<< " [" << i.microseconds() << " ms]"
<< endl;
for( size_t i = 0; i < ret.count; i++ ) for( size_t i = 0; i < ret.count; i++ )
{ {
...@@ -510,12 +534,15 @@ int main( int argc, char** argv ) ...@@ -510,12 +534,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr, reg, count); ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr, reg, count);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << ModbusRTU::dat2str(ret.count) << endl; cout << "(reply): count=" << ModbusRTU::dat2str(ret.count)
<< " [" << i.microseconds() << " ms]"
<< endl;
for( size_t i = 0; i < ret.count; i++ ) for( size_t i = 0; i < ret.count; i++ )
{ {
...@@ -540,10 +567,13 @@ int main( int argc, char** argv ) ...@@ -540,10 +567,13 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::MEIMessageRetRDI ret = mb.read4314(slaveaddr, devID, objID); ModbusRTU::MEIMessageRetRDI ret = mb.read4314(slaveaddr, devID, objID);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): "
<< "[" << i.microseconds() << " ms] "
<< ret << endl;
else else
cout << "(reply): devID='" << (int)ret.devID << "' objNum='" << (int)ret.objNum << "'" << endl << ret.dlist << endl; cout << "(reply): devID='" << (int)ret.devID << "' objNum='" << (int)ret.objNum << "'" << endl << ret.dlist << endl;
} }
...@@ -559,10 +589,13 @@ int main( int argc, char** argv ) ...@@ -559,10 +589,13 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::ForceSingleCoilRetMessage ret = mb.write05(slaveaddr, reg, (bool)val); ModbusRTU::ForceSingleCoilRetMessage ret = mb.write05(slaveaddr, reg, (bool)val);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): "
<< " [" << i.microseconds() << " ms] "
<< ret << endl;
} }
break; break;
...@@ -576,10 +609,13 @@ int main( int argc, char** argv ) ...@@ -576,10 +609,13 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::WriteSingleOutputRetMessage ret = mb.write06(slaveaddr, reg, val); ModbusRTU::WriteSingleOutputRetMessage ret = mb.write06(slaveaddr, reg, val);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): "
<< " [" << i.microseconds() << " ms] "
<< ret << endl;
} }
break; break;
...@@ -596,10 +632,13 @@ int main( int argc, char** argv ) ...@@ -596,10 +632,13 @@ int main( int argc, char** argv )
ModbusRTU::ForceCoilsMessage msg(slaveaddr, reg); ModbusRTU::ForceCoilsMessage msg(slaveaddr, reg);
ModbusRTU::DataBits b(val); ModbusRTU::DataBits b(val);
msg.addData(b); msg.addData(b);
Interval i;
ModbusRTU::ForceCoilsRetMessage ret = mb.write0F(msg); ModbusRTU::ForceCoilsRetMessage ret = mb.write0F(msg);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): "
<< " [" << i.microseconds() << " ms] "
<< ret << endl;
} }
break; break;
...@@ -619,10 +658,13 @@ int main( int argc, char** argv ) ...@@ -619,10 +658,13 @@ int main( int argc, char** argv )
for( int i = 0; i < count; i++ ) for( int i = 0; i < count; i++ )
msg.addData(val); msg.addData(val);
Interval i;
ModbusRTU::WriteOutputRetMessage ret = mb.write10(msg); ModbusRTU::WriteOutputRetMessage ret = mb.write10(msg);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): "
<< " [" << i.microseconds() << " ms] "
<< ret << endl;
} }
break; break;
...@@ -636,12 +678,15 @@ int main( int argc, char** argv ) ...@@ -636,12 +678,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::DiagnosticRetMessage ret = mb.diag08(slaveaddr, subfunc, dat); ModbusRTU::DiagnosticRetMessage ret = mb.diag08(slaveaddr, subfunc, dat);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << ModbusRTU::dat2str(ret.count) << endl; cout << "(reply): count=" << ModbusRTU::dat2str(ret.count)
<< " [" << i.microseconds() << " ms]"
<< endl;
for( size_t i = 0; i < ret.count; i++ ) for( size_t i = 0; i < ret.count; i++ )
{ {
...@@ -719,7 +764,10 @@ int main( int argc, char** argv ) ...@@ -719,7 +764,10 @@ int main( int argc, char** argv )
tofile = s.str(); tofile = s.str();
} }
Interval i;
mb.fileTransfer( slaveaddr, reg, tofile, tout); mb.fileTransfer( slaveaddr, reg, tofile, tout);
if( verb )
cout << i.microseconds() << " ms" << endl;
} }
break; break;
......
...@@ -84,6 +84,23 @@ enum Command ...@@ -84,6 +84,23 @@ enum Command
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static char* checkArg( int ind, int argc, char* argv[] ); static char* checkArg( int ind, int argc, char* argv[] );
// --------------------------------------------------------------------------
struct Interval
{
using time_point = std::chrono::time_point<std::chrono::steady_clock>;
Interval()
:tmStart(std::chrono::steady_clock::now())
{}
uint64_t microseconds()
{
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - tmStart).count();
}
time_point tmStart;
};
// --------------------------------------------------------------------------
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
// std::ios::sync_with_stdio(false); // std::ios::sync_with_stdio(false);
...@@ -352,8 +369,6 @@ int main( int argc, char** argv ) ...@@ -352,8 +369,6 @@ int main( int argc, char** argv )
if( ncycles > 0 ) if( ncycles > 0 )
nc = ncycles; nc = ncycles;
std::chrono::time_point<std::chrono::system_clock> start, end;
while( nc ) while( nc )
{ {
try try
...@@ -370,17 +385,15 @@ int main( int argc, char** argv ) ...@@ -370,17 +385,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
start = std::chrono::system_clock::now(); Interval i;
ModbusRTU::ReadCoilRetMessage ret = mb.read01(slaveaddr, reg, count); ModbusRTU::ReadCoilRetMessage ret = mb.read01(slaveaddr, reg, count);
end = std::chrono::system_clock::now();
int elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << (int)ret.bcnt cout << "(reply): count=" << (int)ret.bcnt
<< "(" << ModbusRTU::dat2str(ret.bcnt) << ")" << "(" << ModbusRTU::dat2str(ret.bcnt) << ")"
<< " usec: " << elapsed_usec << " [" << i.microseconds() << " ms]"
<< endl; << endl;
for( int i = 0; i < ret.bcnt; i++ ) for( int i = 0; i < ret.bcnt; i++ )
...@@ -406,17 +419,15 @@ int main( int argc, char** argv ) ...@@ -406,17 +419,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
start = std::chrono::system_clock::now(); Interval i;
ModbusRTU::ReadInputStatusRetMessage ret = mb.read02(slaveaddr, reg, count); ModbusRTU::ReadInputStatusRetMessage ret = mb.read02(slaveaddr, reg, count);
end = std::chrono::system_clock::now();
int elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << (int)ret.bcnt cout << "(reply): count=" << (int)ret.bcnt
<< "(" << ModbusRTU::dat2str(ret.bcnt) << ")" << "(" << ModbusRTU::dat2str(ret.bcnt) << ")"
<< " usec: " << elapsed_usec << " [" << i.microseconds() << " ms]"
<< endl; << endl;
for( int i = 0; i < ret.bcnt; i++ ) for( int i = 0; i < ret.bcnt; i++ )
...@@ -442,17 +453,15 @@ int main( int argc, char** argv ) ...@@ -442,17 +453,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
start = std::chrono::system_clock::now(); Interval i;
ModbusRTU::ReadOutputRetMessage ret = mb.read03(slaveaddr, reg, count); ModbusRTU::ReadOutputRetMessage ret = mb.read03(slaveaddr, reg, count);
end = std::chrono::system_clock::now();
int elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << (int)ret.count cout << "(reply): count=" << (int)ret.count
<< "(" << ModbusRTU::dat2str(ret.count) << ")" << "(" << ModbusRTU::dat2str(ret.count) << ")"
<< " usec: " << elapsed_usec << " [" << i.microseconds() << " ms]"
<< endl; << endl;
for( size_t i = 0; i < ret.count; i++ ) for( size_t i = 0; i < ret.count; i++ )
...@@ -483,17 +492,15 @@ int main( int argc, char** argv ) ...@@ -483,17 +492,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
start = std::chrono::system_clock::now(); Interval i;
ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr, reg, count); ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr, reg, count);
end = std::chrono::system_clock::now();
int elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << (int)ret.count cout << "(reply): count=" << (int)ret.count
<< "(" << ModbusRTU::dat2str(ret.count) << ")" << "(" << ModbusRTU::dat2str(ret.count) << ")"
<< " usec: " << elapsed_usec << " [" << i.microseconds() << " ms]"
<< endl; << endl;
for( size_t i = 0; i < ret.count; i++ ) for( size_t i = 0; i < ret.count; i++ )
...@@ -524,10 +531,13 @@ int main( int argc, char** argv ) ...@@ -524,10 +531,13 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::MEIMessageRetRDI ret = mb.read4314(slaveaddr, devID, objID); ModbusRTU::MEIMessageRetRDI ret = mb.read4314(slaveaddr, devID, objID);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): "
<< "[" << i.microseconds() << " ms] "
<< ret << endl;
else else
cout << "(reply): devID='" << (int)ret.devID << "' objNum='" << (int)ret.objNum << "'" << endl << ret.dlist << endl; cout << "(reply): devID='" << (int)ret.devID << "' objNum='" << (int)ret.objNum << "'" << endl << ret.dlist << endl;
} }
...@@ -543,14 +553,12 @@ int main( int argc, char** argv ) ...@@ -543,14 +553,12 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
start = std::chrono::system_clock::now(); Interval i;
ModbusRTU::ForceSingleCoilRetMessage ret = mb.write05(slaveaddr, reg, (bool)val); ModbusRTU::ForceSingleCoilRetMessage ret = mb.write05(slaveaddr, reg, (bool)val);
end = std::chrono::system_clock::now();
int elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
if( verb ) if( verb )
cout << "(reply): " << ret cout << "(reply): " << "[" << i.microseconds() << " ms] "
<< " usec: " << elapsed_usec << ret
<< endl; << endl;
} }
break; break;
...@@ -565,14 +573,12 @@ int main( int argc, char** argv ) ...@@ -565,14 +573,12 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
start = std::chrono::system_clock::now(); Interval i;
ModbusRTU::WriteSingleOutputRetMessage ret = mb.write06(slaveaddr, reg, val); ModbusRTU::WriteSingleOutputRetMessage ret = mb.write06(slaveaddr, reg, val);
end = std::chrono::system_clock::now();
int elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
if( verb ) if( verb )
cout << "(reply): " << ret cout << "(reply): " << "[" << i.microseconds() << " ms] "
<< " usec: " << elapsed_usec << ret
<< endl; << endl;
} }
...@@ -591,10 +597,12 @@ int main( int argc, char** argv ) ...@@ -591,10 +597,12 @@ int main( int argc, char** argv )
ModbusRTU::ForceCoilsMessage msg(slaveaddr, reg); ModbusRTU::ForceCoilsMessage msg(slaveaddr, reg);
ModbusRTU::DataBits b(val); ModbusRTU::DataBits b(val);
msg.addData(b); msg.addData(b);
Interval i;
ModbusRTU::ForceCoilsRetMessage ret = mb.write0F(msg); ModbusRTU::ForceCoilsRetMessage ret = mb.write0F(msg);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): [" << i.microseconds() << " ms] "
<< ret << endl;
} }
break; break;
...@@ -617,10 +625,7 @@ int main( int argc, char** argv ) ...@@ -617,10 +625,7 @@ int main( int argc, char** argv )
cout << "}" << endl; cout << "}" << endl;
} }
start = std::chrono::system_clock::now();
ModbusRTU::WriteOutputMessage msg(slaveaddr, reg); ModbusRTU::WriteOutputMessage msg(slaveaddr, reg);
end = std::chrono::system_clock::now();
int elapsed_usec = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
for( const auto& v : data ) for( const auto& v : data )
{ {
...@@ -639,11 +644,12 @@ int main( int argc, char** argv ) ...@@ -639,11 +644,12 @@ int main( int argc, char** argv )
msg.addData(v.d.v); msg.addData(v.d.v);
} }
Interval i;
ModbusRTU::WriteOutputRetMessage ret = mb.write10(msg); ModbusRTU::WriteOutputRetMessage ret = mb.write10(msg);
if( verb ) if( verb )
cout << "(reply): " << ret cout << "(reply): [" << i.microseconds() << " ms] "
<< " usec: " << elapsed_usec << ret
<< endl; << endl;
} }
...@@ -659,12 +665,15 @@ int main( int argc, char** argv ) ...@@ -659,12 +665,15 @@ int main( int argc, char** argv )
<< endl; << endl;
} }
Interval i;
ModbusRTU::DiagnosticRetMessage ret = mb.diag08(slaveaddr, subfunc, dat); ModbusRTU::DiagnosticRetMessage ret = mb.diag08(slaveaddr, subfunc, dat);
if( verb ) if( verb )
cout << "(reply): " << ret << endl; cout << "(reply): " << ret << endl;
cout << "(reply): count=" << ModbusRTU::dat2str(ret.count) << endl; cout << "(reply): count=" << ModbusRTU::dat2str(ret.count)
<< " [" << i.microseconds() << " ms]"
<< endl;
for( size_t i = 0; i < ret.count; i++ ) for( size_t i = 0; i < ret.count; i++ )
{ {
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
<xsl:variable name="ARGPREFIX"> <xsl:variable name="ARGPREFIX">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template> <xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template>
</xsl:variable> </xsl:variable>
<xsl:variable name="LOGROTATE">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'logrotate'"/></xsl:call-template>
</xsl:variable>
<xsl:template match="/"> <xsl:template match="/">
<!-- BEGIN CC-FILE --> <!-- BEGIN CC-FILE -->
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
<xsl:variable name="ARGPREFIX"> <xsl:variable name="ARGPREFIX">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template> <xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template>
</xsl:variable> </xsl:variable>
<xsl:variable name="LOGROTATE">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'logrotate'"/></xsl:call-template>
</xsl:variable>
<xsl:template match="/"> <xsl:template match="/">
<!-- BEGIN CC-FILE --> <!-- BEGIN CC-FILE -->
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
<xsl:variable name="ARGPREFIX"> <xsl:variable name="ARGPREFIX">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template> <xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template>
</xsl:variable> </xsl:variable>
<xsl:variable name="LOGROTATE">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'logrotate'"/></xsl:call-template>
</xsl:variable>
<!-- Генерирование cc-файла --> <!-- Генерирование cc-файла -->
<xsl:template match="/"> <xsl:template match="/">
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
<xsl:variable name="ARGPREFIX"> <xsl:variable name="ARGPREFIX">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template> <xsl:call-template name="settings"><xsl:with-param name="varname" select="'arg-prefix'"/></xsl:call-template>
</xsl:variable> </xsl:variable>
<xsl:variable name="LOGROTATE">
<xsl:call-template name="settings"><xsl:with-param name="varname" select="'logrotate'"/></xsl:call-template>
</xsl:variable>
<!-- Генерирование cc-файла --> <!-- Генерирование cc-файла -->
<xsl:template match="/"> <xsl:template match="/">
......
...@@ -61,10 +61,10 @@ class <xsl:value-of select="$CLASSNAME"/>_SK: ...@@ -61,10 +61,10 @@ class <xsl:value-of select="$CLASSNAME"/>_SK:
{ {
public: public:
<xsl:if test="not(normalize-space($OID))=''"> <xsl:if test="not(normalize-space($OID))=''">
<xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id = uniset::uniset_conf()->getObjectID("<xsl:value-of select="$OID"/>"), xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($OID)"/>"), const std::string&amp; argprefix="" ); <xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id = uniset::uniset_conf()->getObjectID("<xsl:value-of select="$OID"/>"), xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($OID)"/>"), const std::string&amp; argprefix="", xmlNode* globalConfNode=nullptr );
</xsl:if> </xsl:if>
<xsl:if test="normalize-space($OID)=''"> <xsl:if test="normalize-space($OID)=''">
<xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id, xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($OID)"/>") ); <xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id, xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($OID)"/>"), xmlNode* globalConfNode=nullptr );
</xsl:if> </xsl:if>
<xsl:value-of select="$CLASSNAME"/>_SK(); <xsl:value-of select="$CLASSNAME"/>_SK();
......
...@@ -60,10 +60,10 @@ class <xsl:value-of select="$CLASSNAME"/>_SK: ...@@ -60,10 +60,10 @@ class <xsl:value-of select="$CLASSNAME"/>_SK:
{ {
public: public:
<xsl:if test="not(normalize-space($OID))=''"> <xsl:if test="not(normalize-space($OID))=''">
<xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id = uniset::uniset_conf()->getObjectID("<xsl:value-of select="$OID"/>"), xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($CNAME)"/>"), const std::string&amp; argprefix="<xsl:value-of select="normalize-space($ARGPREFIX)"/>" ); <xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id = uniset::uniset_conf()->getObjectID("<xsl:value-of select="$OID"/>"), xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($CNAME)"/>"), const std::string&amp; argprefix="<xsl:value-of select="normalize-space($ARGPREFIX)"/>", xmlNode* globalConfNode=nullptr );
</xsl:if> </xsl:if>
<xsl:if test="normalize-space($OID)=''"> <xsl:if test="normalize-space($OID)=''">
<xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id, xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($CNAME)"/>"), const std::string&amp; argprefix="<xsl:value-of select="normalize-space($ARGPREFIX)"/>" ); <xsl:value-of select="$CLASSNAME"/>_SK( uniset::ObjectId id, xmlNode* node=uniset::uniset_conf()->getNode("<xsl:value-of select="normalize-space($CNAME)"/>"), const std::string&amp; argprefix="<xsl:value-of select="normalize-space($ARGPREFIX)"/>", xmlNode* globalConfNode=nullptr );
</xsl:if> </xsl:if>
<xsl:value-of select="$CLASSNAME"/>_SK(); <xsl:value-of select="$CLASSNAME"/>_SK();
virtual ~<xsl:value-of select="$CLASSNAME"/>_SK(); virtual ~<xsl:value-of select="$CLASSNAME"/>_SK();
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
<xsl:variable name="OID"> <xsl:variable name="OID">
<xsl:call-template name="settings-alone"><xsl:with-param name="varname" select="'ID'"/></xsl:call-template> <xsl:call-template name="settings-alone"><xsl:with-param name="varname" select="'ID'"/></xsl:call-template>
</xsl:variable> </xsl:variable>
<xsl:variable name="LOGROTATE">
<xsl:call-template name="settings-alone"><xsl:with-param name="varname" select="'logrotate'"/></xsl:call-template>
</xsl:variable>
<!-- Генерирование main для UniSet_FSM --> <!-- Генерирование main для UniSet_FSM -->
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
<set name="sleep-msec" val="150"/> <set name="sleep-msec" val="150"/>
<set name="arg-prefix" val="test-"/> <set name="arg-prefix" val="test-"/>
<set name="resetMsgTime" val="300"/> <set name="resetMsgTime" val="300"/>
<set name="logrotate" val="truncate"/>
</settings> </settings>
<variables> <variables>
<!-- type = [int,str,bool,float] <!-- type = [int,str,bool,float]
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
Name: libuniset2 Name: libuniset2
Version: 2.8 Version: 2.8
Release: alt2.M80P.3 Release: alt7.M80P.8
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
License: LGPL License: LGPL
...@@ -546,9 +546,24 @@ rm -f %buildroot%_docdir/%oname/html/*.md5 ...@@ -546,9 +546,24 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
# history of current unpublished changes # history of current unpublished changes
%changelog %changelog
* Tue Feb 05 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt2.M80P.3 * Mon Mar 18 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt7.M80P.8
- backport to ALTLinux p8 (by rpmbph script) - backport to ALTLinux p8 (by rpmbph script)
* Mon Mar 18 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt8
- minor fixes
* Sun Feb 24 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt7
- (LogDB): added support write logfiles
* Mon Feb 11 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt6
- (TSDB): reopen connection for error "broken pipe"
* Sat Feb 09 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt5
- (uniset-codegen): setup logrotate command
* Tue Feb 05 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt4
- (PGSQL): fix SIGSEGV in flushInsertBuffer()
* Tue Feb 05 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt3 * Tue Feb 05 2019 Pavel Vainerman <pv@altlinux.ru> 2.8-alt3
- (admin): fix error in "sendText" funciton - (admin): fix error in "sendText" funciton
......
...@@ -76,6 +76,7 @@ ...@@ -76,6 +76,7 @@
<set name="class-name" val="TestGen"/> <set name="class-name" val="TestGen"/>
<set name="msg-count" val="20"/> <set name="msg-count" val="20"/>
<set name="sleep-msec" val="150"/> <set name="sleep-msec" val="150"/>
<set name="logrotate" val="append"/>
</settings> </settings>
<variables> <variables>
<!-- type = [int,str,bool,float] <!-- type = [int,str,bool,float]
...@@ -285,6 +286,17 @@ ...@@ -285,6 +286,17 @@
А также такой процесс потребляет больше процессорного времени, т.к. постоянно опрашивает "входы" независимо от того, меняли ли они А также такой процесс потребляет больше процессорного времени, т.к. постоянно опрашивает "входы" независимо от того, меняли ли они
своё состояние. своё состояние.
\section pg_Codegen_Logrotate Настройка ротации логов
В разделе '<settings>' можно задавать параметр \b logrotate=[truncate|append]. Он определяет как будет обработана
команда SystemMessage::Logrotate, по которой происходит переоткрытие логфайла (если включено ведение логфайла).
- \b truncate - при переоткрытии "обрезать" файл
- \b append - при переоткрытии продолжить писать логи в конец файла
Режим \b append используется по умолчанию. Он удобен для использования совместно с внешней системой ротации логов,
например logrotate. Которая после проведения ротации может обрезать файл и посылать ВСЕМ процессам команду LogRotate по которой
файл логов будет переоткрыт, если он был заархивирован. При этом те процессы чей файл не был заархивирован, продолжат
писать дальше в конец логфайла.
\section pg_Codegen_Templ_Alone Шаблон 'Alone' \section pg_Codegen_Templ_Alone Шаблон 'Alone'
Шаблон \b "Alone" предназначен для генерирования \b без \b использования специального xml-файла с описанием переменных. Шаблон \b "Alone" предназначен для генерирования \b без \b использования специального xml-файла с описанием переменных.
Генерирование происходит непосредственно по конфигурационному файлу проекта. Для этого всё-равно необходимо создать Генерирование происходит непосредственно по конфигурационному файлу проекта. Для этого всё-равно необходимо создать
......
...@@ -365,9 +365,16 @@ bool BackendOpenTSDB::flushBuffer() ...@@ -365,9 +365,16 @@ bool BackendOpenTSDB::flushBuffer()
return true; return true;
} }
catch( Poco::IOException& ex )
{
mywarn << "(flushBuffer): (io): " << ex.displayText() << endl;
lastError = ex.displayText();
if( !reconnect() )
askTimer(tmReconnect, reconnectTime);
}
catch( std::exception& ex ) catch( std::exception& ex )
{ {
mywarn << "(flushBuffer): " << ex.what() << endl; mywarn << "(flushBuffer): (std): " << ex.what() << endl;
lastError = ex.what(); lastError = ex.what();
} }
......
...@@ -212,12 +212,9 @@ void DBServer_PostgreSQL::flushBuffer() ...@@ -212,12 +212,9 @@ void DBServer_PostgreSQL::flushBuffer()
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
void DBServer_PostgreSQL::flushInsertBuffer() void DBServer_PostgreSQL::flushInsertBuffer()
{ {
if( !db || !connect_ok ) if( ibufSize > ibufMaxSize )
{ {
if( ibufSize < ibufMaxSize ) dbcrit << myname << "(flushWriteBuffer): "
return;
dbcrit << myname << "(flushWriteBuffer): DB not connected!"
<< " buffer[" << ibufSize << "] overflow! LOST DATA..." << endl; << " buffer[" << ibufSize << "] overflow! LOST DATA..." << endl;
// Чистим заданное число // Чистим заданное число
...@@ -228,26 +225,29 @@ void DBServer_PostgreSQL::flushInsertBuffer() ...@@ -228,26 +225,29 @@ void DBServer_PostgreSQL::flushInsertBuffer()
// Удаляем последние (новые) // Удаляем последние (новые)
if( lastRemove ) if( lastRemove )
{ {
std::advance(beg, -delnum); end = std::prev(end, delnum);
} }
else else
{ {
// Удаляем первые (старые) // Удаляем первые (старые)
std::advance(end, delnum); beg = std::next(beg, delnum);
} }
ibuf.erase(beg, end); if( beg != ibuf.end() )
ibuf.erase(beg, end);
// ibufSize - беззнаковое, так что надо аккуратно // ibufSize - беззнаковое, так что надо аккуратно
ibufSize = (delnum < ibufSize) ? (ibufSize - delnum) : 0; ibufSize = (delnum < ibufSize) ? (ibufSize - delnum) : 0;
dbwarn << myname << "(flushInsertBuffer): overflow: clear data " << delnum << " records." << endl; dbwarn << myname << "(flushInsertBuffer): overflow: clear data " << delnum << " records." << endl;
return;
} }
if( ibufSize == 0 ) if( ibufSize == 0 )
return; return;
if( !db || !connect_ok )
return;
dbinfo << myname << "(flushInsertBuffer): write insert buffer[" << ibufSize << "] to DB.." << endl; dbinfo << myname << "(flushInsertBuffer): write insert buffer[" << ibufSize << "] to DB.." << endl;
if( !writeInsertBufferToDB("main_history", tblcols, ibuf) ) if( !writeInsertBufferToDB("main_history", tblcols, ibuf) )
......
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
ulimit -Sc 1000000 ulimit -Sc 1000000
uniset2-start.sh -f ./uniset2-pgsql-dbserver --confile test.xml --name DBServer1 \ uniset2-start.sh -f ./uniset2-pgsql-dbserver --confile test.xml --name DBServer1 \
--pgsql-dbserver-buffer-size 100 \ --pgsql-buffer-size 100 \
--pgsql-log-add-levels any $* --pgsql-log-add-levels any $*
...@@ -190,6 +190,18 @@ LogDB::LogDB( const string& name, int argc, const char* const* argv, const strin ...@@ -190,6 +190,18 @@ LogDB::LogDB( const string& name, int argc, const char* const* argv, const strin
if( !dbDisabled ) if( !dbDisabled )
l->signal_on_read().connect(sigc::mem_fun(this, &LogDB::addLog)); l->signal_on_read().connect(sigc::mem_fun(this, &LogDB::addLog));
auto lfile = sit.getProp("logfile");
if( !lfile.empty() )
{
l->logfile = make_shared<DebugStream>();
l->logfile->logFile(lfile, false);
l->logfile->level(Debug::ANY);
l->logfile->showDateTime(false);
l->logfile->showLogType(false);
l->logfile->disableOnScreen();
l->signal_on_read().connect(sigc::mem_fun(this, &LogDB::log2File));
}
// l->set(loop); // l->set(loop);
logservers.push_back(l); logservers.push_back(l);
...@@ -398,6 +410,14 @@ void LogDB::addLog( LogDB::Log* log, const string& txt ) ...@@ -398,6 +410,14 @@ void LogDB::addLog( LogDB::Log* log, const string& txt )
qbuf.emplace(q.str()); qbuf.emplace(q.str());
} }
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
void LogDB::log2File( LogDB::Log* log, const string& txt )
{
if( !log->logfile || !log->logfile->isOnLogFile() )
return;
log->logfile->any() << txt << endl;
}
//--------------------------------------------------------------------------------------------
size_t LogDB::getCountOfRecords( const std::string& logname ) size_t LogDB::getCountOfRecords( const std::string& logname )
{ {
ostringstream q; ostringstream q;
......
...@@ -54,6 +54,7 @@ namespace uniset ...@@ -54,6 +54,7 @@ namespace uniset
- \ref sec_LogDB_WEBSOCK - \ref sec_LogDB_WEBSOCK
- \ref sec_LogDB_DETAIL - \ref sec_LogDB_DETAIL
- \ref sec_LogDB_ADMIN - \ref sec_LogDB_ADMIN
- \ref sec_LogDB_LOGFILE
\section sec_LogDB_Comm Общее описание работы LogDB \section sec_LogDB_Comm Общее описание работы LogDB
...@@ -72,7 +73,7 @@ namespace uniset ...@@ -72,7 +73,7 @@ namespace uniset
<LogDB name="LogDB" ...> <LogDB name="LogDB" ...>
<logserver name="" ip=".." port=".." cmd=".." description=".."/> <logserver name="" ip=".." port=".." cmd=".." description=".."/>
<logserver name="" ip=".." port=".." cmd=".." description=".."/> <logserver name="" ip=".." port=".." cmd=".." description=".."/>
<logserver name="" ip=".." port=".." cmd=".."/> <logserver name="" ip=".." port=".." cmd=".." logfile=".."/>
</LogDB> </LogDB>
\endcode \endcode
...@@ -135,6 +136,10 @@ namespace uniset ...@@ -135,6 +136,10 @@ namespace uniset
Количество создаваемых websocket-ов можно ограничить при помощи параметр maxWebsockets (--prefix-ws-max). Количество создаваемых websocket-ов можно ограничить при помощи параметр maxWebsockets (--prefix-ws-max).
\section sec_LogDB_LOGFILE LogDB: Файлы логов
Несмотря на то, что все логи сохраняются в БД, их так же можно писать в файлы.
Для этого каждому логу достаточно указать свойство \b logfile в настройках (см. \ref sec_LogDB_Conf)
\section sec_LogDB_DETAIL LogDB: Технические детали \section sec_LogDB_DETAIL LogDB: Технические детали
Вся реализация построена на "однопоточном" eventloop. В нём происходит, Вся реализация построена на "однопоточном" eventloop. В нём происходит,
...@@ -207,6 +212,7 @@ namespace uniset ...@@ -207,6 +212,7 @@ namespace uniset
void onCheckBuffer( ev::timer& t, int revents ); void onCheckBuffer( ev::timer& t, int revents );
void onActivate( ev::async& watcher, int revents ) ; void onActivate( ev::async& watcher, int revents ) ;
void addLog( Log* log, const std::string& txt ); void addLog( Log* log, const std::string& txt );
void log2File( Log* log, const std::string& txt );
size_t getCountOfRecords( const std::string& logname = "" ); size_t getCountOfRecords( const std::string& logname = "" );
size_t getFirstOfOldRecord( size_t maxnum ); size_t getFirstOfOldRecord( size_t maxnum );
...@@ -270,6 +276,7 @@ namespace uniset ...@@ -270,6 +276,7 @@ namespace uniset
std::string description; std::string description;
std::shared_ptr<DebugStream> dblog; std::shared_ptr<DebugStream> dblog;
std::shared_ptr<DebugStream> logfile;
bool isConnected() const; bool isConnected() const;
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LogDB name="LogDB"> <LogDB name="LogDB">
<logserver name="logserver1" ip="localhost" port="3333" cmd="" description="Лог сервер процесса управления N1"/> <logserver name="logserver1" ip="localhost" port="3333" cmd="" description="Лог сервер процесса управления N1" logfile="/tmp/uniset-test.log"/>
</LogDB> </LogDB>
...@@ -86,9 +86,21 @@ function logdb_test_http_list() ...@@ -86,9 +86,21 @@ function logdb_test_http_list()
logdb_error "test_http_list" "get list must contain 'logserver1'" logdb_error "test_http_list" "get list must contain 'logserver1'"
return 1 return 1
} }
# see config
LOGFILE="/tmp/uniset-test.log"
function logdb_test_logfile()
{
test -f $LOGFILE && return 0
logdb_error "test_logfile" "not found logfile: $LOGFILE"
return 1
}
# ------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------
function logdb_run_all_tests() function logdb_run_all_tests()
{ {
rm -f $LOGFILE
logdb_run_logserver || return 1 logdb_run_logserver || return 1
sleep 3 sleep 3
logdb_run || return 1 logdb_run || return 1
...@@ -98,6 +110,10 @@ function logdb_run_all_tests() ...@@ -98,6 +110,10 @@ function logdb_run_all_tests()
logdb_test_count || RET=1 logdb_test_count || RET=1
logdb_test_http_count || RET=1 logdb_test_http_count || RET=1
logdb_test_http_list || RET=1 logdb_test_http_list || RET=1
logdb_test_logfile || RET 1
# ==== finished ===
rm -f $LOGFILE
} }
create_test_db || exit 1 create_test_db || exit 1
......
...@@ -1815,7 +1815,7 @@ namespace uniset ...@@ -1815,7 +1815,7 @@ namespace uniset
i++; i++;
} }
std::advance(it, sub); it = std::next(it, sub);
regID += sub; regID += sub;
} }
else else
......
...@@ -308,131 +308,151 @@ TEST_CASE("(0x0F): force multiple coils", "[modbus][mbslave][mbtcpslave]") ...@@ -308,131 +308,151 @@ TEST_CASE("(0x0F): force multiple coils", "[modbus][mbslave][mbtcpslave]")
} }
} }
#endif #endif
TEST_CASE("(0x10): write register outputs or memories", "[modbus][mbslave][mbtcpslave]") TEST_CASE("(0x10): write one register", "[modbus][mbslave][mbtcpslave]")
{ {
InitTest(); InitTest();
ObjectId tID = 1025;
ModbusRTU::ModbusData tREG = 18;
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG);
msg.addData(10);
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 1 );
REQUIRE( ui->getValue(tID) == 10 );
}
TEST_CASE("(0x10): write 3 register", "[modbus][mbslave][mbtcpslave][write3]")
{
InitTest(); InitTest();
ObjectId tID = 1025; ObjectId tID = 1025;
ModbusRTU::ModbusData tREG = 18; ModbusRTU::ModbusData tREG = 18;
SECTION("Test: write one register")
{ ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG);
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG); msg.addData(10);
msg.addData(10); msg.addData(11);
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg); msg.addData(12);
REQUIRE( ret.start == tREG ); ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.quant == 1 ); REQUIRE( ret.start == tREG );
REQUIRE( ui->getValue(tID) == 10 ); REQUIRE( ret.quant == 3 );
} REQUIRE( ui->getValue(tID) == 10 );
SECTION("Test: write 3 register") REQUIRE( ui->getValue(tID + 1) == 11 );
{ REQUIRE( ui->getValue(tID + 2) == 1 ); // 1 - т.к. это "DI"
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG); }
msg.addData(10); TEST_CASE("(0x10): write negative value", "[modbus][mbslave][mbtcpslave]")
msg.addData(11); {
msg.addData(12); InitTest();
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg); ObjectId tID = 1025;
REQUIRE( ret.start == tREG ); ModbusRTU::ModbusData tREG = 18;
REQUIRE( ret.quant == 3 ); ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG);
REQUIRE( ui->getValue(tID) == 10 ); msg.addData(-10);
REQUIRE( ui->getValue(tID + 1) == 11 ); msg.addData(-100);
REQUIRE( ui->getValue(tID + 2) == 1 ); // 1 - т.к. это "DI" ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
} REQUIRE( ret.start == tREG );
SECTION("Test: write negative value") REQUIRE( ret.quant == 2 );
REQUIRE( (int16_t)ui->getValue(tID) == -10 );
REQUIRE( (int16_t)ui->getValue(tID + 1) == -100 );
}
TEST_CASE("(0x10): write zero registers", "[modbus][mbslave][mbtcpslave]")
{
InitTest();
ObjectId tID = 1025;
ModbusRTU::ModbusData tREG = 18;
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG);
msg.addData(0);
msg.addData(0);
msg.addData(0);
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 3 );
REQUIRE( ui->getValue(tID) == 0 );
REQUIRE( ui->getValue(tID + 1) == 0 );
REQUIRE( ui->getValue(tID + 2) == 0 );
}
TEST_CASE("(0x10): write OVERFLOW VALUE", "[modbus][mbslave][mbtcpslave]")
{
WARN("FIXME: what to do in this situation?!");
#if 0
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(slaveaddr, 15, 100000);
REQUIRE( ret.start == 15 );
REQUIRE( ret.data == 34464 );
REQUIRE( ui->getValue(1008) == 34464 );
#endif
}
TEST_CASE("(0x10): write 2 good registers and unknown register", "[modbus][mbslave][mbtcpslave]")
{
InitTest();
ObjectId tID = 1025;
ModbusRTU::ModbusData tREG = 18;
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 1);
msg.addData(10);
msg.addData(11);
msg.addData(12); // BAD REG..
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG + 1 );
WARN("FIXME: 'ret.quant' must be '3' or '2'?!");
REQUIRE( ret.quant == 3 ); // "2" ?!! \TODO узнать как нужно поступать по стандарту!
REQUIRE( ui->getValue(tID + 1) == 10 );
REQUIRE( ui->getValue(tID + 2) == 1 ); // 1 - т.к. это "DI"
REQUIRE( ui->getValue(tID + 3) == 0 );
}
TEST_CASE("(0x10): write ALL unknown registers", "[modbus][mbslave][mbtcpslave]")
{
InitTest();
ObjectId tID = 1025;
ModbusRTU::ModbusData tREG = 18;
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 20000);
msg.addData(10);
msg.addData(11);
msg.addData(12);
try
{ {
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG); mb->write10(msg);
msg.addData(-10);
msg.addData(-100);
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 2 );
REQUIRE( (int16_t)ui->getValue(tID) == -10 );
REQUIRE( (int16_t)ui->getValue(tID + 1) == -100 );
} }
SECTION("Test: write zero registers") catch( ModbusRTU::mbException& ex )
{ {
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG); REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
msg.addData(0);
msg.addData(0);
msg.addData(0);
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 3 );
REQUIRE( ui->getValue(tID) == 0 );
REQUIRE( ui->getValue(tID + 1) == 0 );
REQUIRE( ui->getValue(tID + 2) == 0 );
} }
SECTION("Test: write OVERFLOW VALUE") }
TEST_CASE("(0x10): write bad format packet..(incorrect data count)", "[modbus][mbslave][mbtcpslave]")
{
InitTest();
ObjectId tID = 1025;
ModbusRTU::ModbusData tREG = 18;
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 20000);
msg.addData(10);
msg.addData(11);
msg.addData(12);
msg.quant -= 1;
try
{ {
WARN("FIXME: what to do in this situation?!"); mb->write10(msg);
#if 0
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(slaveaddr, 15, 100000);
REQUIRE( ret.start == 15 );
REQUIRE( ret.data == 34464 );
REQUIRE( ui->getValue(1008) == 34464 );
#endif
} }
SECTION("Test: write 2 good registers and unknown register") catch( ModbusRTU::mbException& ex )
{ {
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 1); REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
msg.addData(10);
msg.addData(11);
msg.addData(12); // BAD REG..
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG + 1 );
WARN("FIXME: 'ret.quant' must be '3' or '2'?!");
REQUIRE( ret.quant == 3 ); // "2" ?!! \TODO узнать как нужно поступать по стандарту!
REQUIRE( ui->getValue(tID + 1) == 10 );
REQUIRE( ui->getValue(tID + 2) == 1 ); // 1 - т.к. это "DI"
REQUIRE( ui->getValue(tID + 3) == 0 );
} }
SECTION("Test: write ALL unknown registers") }
{ TEST_CASE("(0x10): write bad format packet..(incorrect size of bytes)", "[modbus][mbslave][mbtcpslave]")
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 20000); {
msg.addData(10); InitTest();
msg.addData(11); ObjectId tID = 1025;
msg.addData(12); ModbusRTU::ModbusData tREG = 18;
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 20000);
msg.addData(10);
msg.addData(11);
msg.addData(12);
msg.bcnt -= 1;
try try
{
mb->write10(msg);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
}
}
SECTION("Test: write bad format packet..(incorrect data count)")
{ {
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 20000); mb->write10(msg);
msg.addData(10);
msg.addData(11);
msg.addData(12);
msg.quant -= 1;
try
{
mb->write10(msg);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
}
} }
SECTION("Test: write bad format packet..(incorrect size of bytes)") catch( ModbusRTU::mbException& ex )
{ {
ModbusRTU::WriteOutputMessage msg(slaveaddr, tREG + 20000); REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
msg.addData(10);
msg.addData(11);
msg.addData(12);
msg.bcnt -= 1;
try
{
mb->write10(msg);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
}
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ. ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/ */
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// generate timestamp: 2019-02-02+03:00 // generate timestamp: 2019-02-11+03:00
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#ifndef UObject_SK_H_ #ifndef UObject_SK_H_
#define UObject_SK_H_ #define UObject_SK_H_
...@@ -29,7 +29,7 @@ class UObject_SK: ...@@ -29,7 +29,7 @@ class UObject_SK:
public uniset::UniSetObject public uniset::UniSetObject
{ {
public: public:
UObject_SK( uniset::ObjectId id, xmlNode* node=uniset::uniset_conf()->getNode("UObject"), const std::string& argprefix="" ); UObject_SK( uniset::ObjectId id, xmlNode* node=uniset::uniset_conf()->getNode("UObject"), const std::string& argprefix="", xmlNode* globalConfNode=nullptr );
UObject_SK(); UObject_SK();
virtual ~UObject_SK(); virtual ~UObject_SK();
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ. ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/ */
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// generate timestamp: 2019-02-02+03:00 // generate timestamp: 2019-02-11+03:00
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <memory> #include <memory>
#include <iomanip> #include <iomanip>
...@@ -56,6 +56,21 @@ end_private(false) ...@@ -56,6 +56,21 @@ end_private(false)
throw uniset::Exception( std::string(myname+": init failed!!!") ); throw uniset::Exception( std::string(myname+": init failed!!!") );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ( val, confval, globalval, default val )
static const std::string init4_str( const std::string& s1, const std::string& s2,
const std::string& s3, const std::string& s4 )
{
if( !s1.empty() )
return s1;
if( !s2.empty() )
return s2;
if( !s3.empty() )
return s3;
return s4;
}
// -----------------------------------------------------------------------------
// ( val, confval, default val ) // ( val, confval, default val )
static const std::string init3_str( const std::string& s1, const std::string& s2, const std::string& s3 ) static const std::string init3_str( const std::string& s1, const std::string& s2, const std::string& s3 )
{ {
...@@ -80,7 +95,7 @@ static uniset::ObjectId init_node( xmlNode* cnode, const std::string& prop ) ...@@ -80,7 +95,7 @@ static uniset::ObjectId init_node( xmlNode* cnode, const std::string& prop )
return conf->getNodeID(conf->getProp(cnode,prop)); return conf->getNodeID(conf->getProp(cnode,prop));
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argprefix ): UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argprefix, xmlNode* globalnode ):
UniSetObject(id), UniSetObject(id),
// Инициализация идентификаторов (имена берутся из конф. файла) // Инициализация идентификаторов (имена берутся из конф. файла)
...@@ -179,7 +194,7 @@ end_private(false) ...@@ -179,7 +194,7 @@ end_private(false)
if( s_resetTime.empty() ) // -V547 if( s_resetTime.empty() ) // -V547
s_resetTime = "500"; s_resetTime = "500";
resetMsgTime = uni_atoi(init3_str(conf->getArgParam("--" + argprefix + "resetMsgTime"),conf->getProp(cnode,"resetMsgTime"),s_resetTime)); resetMsgTime = uni_atoi(init4_str(conf->getArgParam("--" + argprefix + "resetMsgTime"),conf->getProp(cnode,"resetMsgTime"),conf->getProp(globalnode,"resetMsgTime"), s_resetTime));
ptResetMsg.setTiming(resetMsgTime); ptResetMsg.setTiming(resetMsgTime);
int sm_tout = conf->getArgInt("--" + argprefix + "sm-ready-timeout",""); int sm_tout = conf->getArgInt("--" + argprefix + "sm-ready-timeout","");
...@@ -190,7 +205,7 @@ end_private(false) ...@@ -190,7 +205,7 @@ end_private(false)
else else
smReadyTimeout = sm_tout; smReadyTimeout = sm_tout;
smTestID = conf->getSensorID(init3_str(conf->getArgParam("--" + argprefix + "sm-test-id"),conf->getProp(cnode,"smTestID"),"")); smTestID = conf->getSensorID(init4_str(conf->getArgParam("--" + argprefix + "sm-test-id"),conf->getProp(cnode,"smTestID"),conf->getProp(globalnode,"smTestID"),""));
if( smTestID == DefaultObjectId ) // -V547 if( smTestID == DefaultObjectId ) // -V547
...@@ -491,7 +506,9 @@ void UObject_SK::preSysCommand( const SystemMessage* _sm ) ...@@ -491,7 +506,9 @@ void UObject_SK::preSysCommand( const SystemMessage* _sm )
string fname( log()->getLogFile() ); string fname( log()->getLogFile() );
if( !fname.empty() ) if( !fname.empty() )
{ {
mylog->logFile(fname.c_str(),true);
mylog->logFile(fname.c_str(),false);
mylogany << myname << "(preSysCommand): ***************** mylog LOG ROTATE *****************" << endl; mylogany << myname << "(preSysCommand): ***************** mylog LOG ROTATE *****************" << endl;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
// but should be adaptable to any project. // but should be adaptable to any project.
// (c) 2002 adapted for UniSet by Lav, GNU LGPL license // (c) 2002 adapted for UniSet by Lav, GNU LGPL license
// Modify for UniSet by pv@eterspft.ru, GNU LGPL license // Modify for UniSet by pv@etersoft.ru, GNU LGPL license
#ifndef DEBUGSTREAM_H #ifndef DEBUGSTREAM_H
#define DEBUGSTREAM_H #define DEBUGSTREAM_H
...@@ -68,7 +68,7 @@ struct Debug ...@@ -68,7 +68,7 @@ struct Debug
If you want to have debug output from time critical code you should If you want to have debug output from time critical code you should
use this construct: use this construct:
if (debug..is_info()) { if (debug.is_info()) {
debug << "...debug output...\n"; debug << "...debug output...\n";
} }
...@@ -160,6 +160,12 @@ class DebugStream : public std::ostream ...@@ -160,6 +160,12 @@ class DebugStream : public std::ostream
logFile(""); logFile("");
} }
// enable print on screen
void enableOnScreen();
// disable print onscreen
void disableOnScreen();
/// Returns true if t is part of the current debug level. /// Returns true if t is part of the current debug level.
inline bool debugging(Debug::type t = Debug::ANY) const noexcept inline bool debugging(Debug::type t = Debug::ANY) const noexcept
{ {
...@@ -297,6 +303,7 @@ class DebugStream : public std::ostream ...@@ -297,6 +303,7 @@ class DebugStream : public std::ostream
std::string logname = { "" }; std::string logname = { "" };
bool isWriteLogFile = { false }; bool isWriteLogFile = { false };
bool onScreen = { true };
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#endif #endif
...@@ -134,11 +134,39 @@ void DebugStream::logFile( const std::string& f, bool truncate ) ...@@ -134,11 +134,39 @@ void DebugStream::logFile( const std::string& f, bool truncate )
mode |= truncate ? ios::trunc : ios::app; mode |= truncate ? ios::trunc : ios::app;
internal->fbuf.open(f.c_str(), mode); internal->fbuf.open(f.c_str(), mode);
delete rdbuf(new threebuf(cerr.rdbuf(),
&internal->fbuf, &internal->sbuf)); if( onScreen )
{
delete rdbuf(new threebuf(cerr.rdbuf(),
&internal->fbuf, &internal->sbuf));
}
else
{
// print to cerr disabled
delete rdbuf(new teebuf(&internal->fbuf, &internal->sbuf));
}
} }
else else
delete rdbuf(new teebuf(cerr.rdbuf(), &internal->sbuf)); {
if( onScreen )
delete rdbuf(new teebuf(cerr.rdbuf(), &internal->sbuf));
else
delete rdbuf(&internal->sbuf);
}
}
//--------------------------------------------------------------------------
void DebugStream::enableOnScreen()
{
onScreen = true;
// reopen streams
logFile(fname,false);
}
//--------------------------------------------------------------------------
void DebugStream::disableOnScreen()
{
onScreen = false;
// reopen streams
logFile(fname,false);
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
std::ostream& DebugStream::debug(Debug::type t) noexcept std::ostream& DebugStream::debug(Debug::type t) noexcept
......
...@@ -430,6 +430,11 @@ void LogReader::readlogs( const std::string& _addr, int _port, LogServerTypes::C ...@@ -430,6 +430,11 @@ void LogReader::readlogs( const std::string& _addr, int _port, LogServerTypes::C
{ {
cerr << "(LogReader): " << e.displayText() << " (" << _addr << ")" << endl; cerr << "(LogReader): " << e.displayText() << " (" << _addr << ")" << endl;
} }
catch( Poco::IOException& e )
{
cerr << "(LogReader): " << e.displayText() << " (" << _addr << ")" << endl;
disconnect();
}
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
cerr << "(LogReader): " << ex.what() << endl; cerr << "(LogReader): " << ex.what() << endl;
...@@ -470,6 +475,10 @@ void LogReader::sendCommand(LogServerTypes::lsMessage& msg, bool verbose ) ...@@ -470,6 +475,10 @@ void LogReader::sendCommand(LogServerTypes::lsMessage& msg, bool verbose )
{ {
cerr << "(LogReader): send error: " << e.displayText() << endl; // " (" << _addr << ")" << endl; cerr << "(LogReader): send error: " << e.displayText() << endl; // " (" << _addr << ")" << endl;
} }
catch( Poco::IOException& ex )
{
cerr << "(LogReader): send error: " << ex.displayText() << endl;
}
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
cerr << "(LogReader): send error: " << ex.what() << endl; cerr << "(LogReader): send error: " << ex.what() << endl;
......
...@@ -128,7 +128,7 @@ void ObjectRepository::registration(const string& name, const ObjectPtr oRef, co ...@@ -128,7 +128,7 @@ void ObjectRepository::registration(const string& name, const ObjectPtr oRef, co
} }
catch(const CosNaming::NamingContext::AlreadyBound&) catch(const CosNaming::NamingContext::AlreadyBound&)
{ {
uwarn << "(registration): " << name << " уже зарегестрирован в " << section << "!!!" << endl; uwarn << "(registration): " << name << " уже зарегистрирован в " << section << "!!!" << endl;
if( !force ) if( !force )
throw ObjectNameAlready(); throw ObjectNameAlready();
......
...@@ -156,6 +156,9 @@ string UniXML::getProp2(const xmlNode* node, const string& name, const string& d ...@@ -156,6 +156,9 @@ string UniXML::getProp2(const xmlNode* node, const string& name, const string& d
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
string UniXML::getProp(const xmlNode* node, const string& name) noexcept string UniXML::getProp(const xmlNode* node, const string& name) noexcept
{ {
if( !node )
return "";
xmlChar* text = ::xmlGetProp((xmlNode*)node, (const xmlChar*)name.c_str()); xmlChar* text = ::xmlGetProp((xmlNode*)node, (const xmlChar*)name.c_str());
if( text == NULL ) if( text == NULL )
......
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