Commit f3d8fb27 authored by Pavel Vainerman's avatar Pavel Vainerman

(ModbusSlave): переделал структуру тестов..

parent 9bddf978
...@@ -100,15 +100,54 @@ ...@@ -100,15 +100,54 @@
<!-- ************************ Датчики ********************** --> <!-- ************************ Датчики ********************** -->
<sensors name="Sensors"> <sensors name="Sensors">
<item default="1" id="1000" mbs="1" mbreg="0x01" nbit="0" iotype="DI" name="TestReadCoil_S" textname="Тестовый регистр для ReadCoil"/> <item default="1" id="1000" mbs="1" mbreg="1" iotype="DI" name="TestReadCoil1_S" textname="Тестовый регистр для ReadCoil"/>
<item default="1" id="1001" mbs="1" mbreg="0x01" nbit="1" iotype="DI" name="TestReadCoil_S" textname="Тестовый регистр для ReadCoil"/> <item default="1" id="1001" mbs="1" mbreg="2" iotype="DI" name="TestReadCoil2_S" textname="Тестовый регистр для ReadCoil"/>
<item id="1002" mbs="1" mbreg="0x01" nbit="2" iotype="DI" name="TestReadCoil_S" textname="Тестовый регистр для ReadCoil"/> <item id="1002" mbs="1" mbreg="3" iotype="DI" name="TestReadCoil3_S" textname="Тестовый регистр для ReadCoil"/>
<item default="10" id="1003" mbs="1" mbreg="10" iotype="AI" name="TestRead03" textname="Тестовый регистр для 0x03"/> <item default="10" id="1003" mbs="1" mbreg="10" iotype="AI" name="TestRead03_1" textname="Тестовый регистр для 0x03"/>
<item default="11" id="1004" mbs="1" mbreg="11" iotype="AI" name="TestRead03" textname="Тестовый регистр для 0x03"/> <item default="11" id="1004" mbs="1" mbreg="11" iotype="AI" name="TestRead03_2" textname="Тестовый регистр для 0x03"/>
<item default="-10" id="1005" mbs="1" mbreg="12" iotype="AI" name="TestRead03" textname="Тестовый регистр для 0x03"/> <item default="-10" id="1005" mbs="1" mbreg="12" iotype="AI" name="TestRead03_3" textname="Тестовый регистр для 0x03"/>
<item default="-10000" id="1006" mbs="1" mbreg="13" iotype="AI" name="TestRead03" textname="Тестовый регистр для 0x03"/> <item default="-10000" id="1006" mbs="1" mbreg="13" iotype="AI" name="TestRead03_4" textname="Тестовый регистр для 0x03"/>
<item id="1007" mbs="1" mbreg="14" iotype="AI" name="TestRead05" textname="Тестовый регистр для 0x05"/> <item id="1007" mbs="1" mbreg="14" iotype="AI" name="TestRead05" textname="Тестовый регистр для 0x05"/>
<item id="1008" mbs="1" mbreg="15" iotype="AI" name="TestRead06" textname="Тестовый регистр для 0x06"/>
<item id="1009" mbs="1" mbreg="16" nbit="0" iotype="DI" name="TestForceCoil0_S" textname="Тестовый регистр для force coil"/>
<item id="1010" mbs="1" mbreg="16" nbit="1" iotype="DI" name="TestForceCoil1_S" textname="Тестовый регистр для force coil"/>
<item id="1011" mbs="1" mbreg="16" nbit="2" iotype="DI" name="TestForceCoil2_S" textname="Тестовый регистр для force coil"/>
<item id="1012" mbs="1" mbreg="16" nbit="3" iotype="DI" name="TestForceCoil3_S" textname="Тестовый регистр для force coil"/>
<item id="1013" mbs="1" mbreg="16" nbit="4" iotype="DI" name="TestForceCoil4_S" textname="Тестовый регистр для force coil"/>
<item id="1014" mbs="1" mbreg="16" nbit="5" iotype="DI" name="TestForceCoil5_S" textname="Тестовый регистр для force coil"/>
<item id="1015" mbs="1" mbreg="16" nbit="6" iotype="DI" name="TestForceCoil6_S" textname="Тестовый регистр для force coil"/>
<item id="1016" mbs="1" mbreg="16" nbit="7" iotype="DI" name="TestForceCoil7_S" textname="Тестовый регистр для force coil"/>
<item id="1017" mbs="1" mbreg="17" nbit="0" iotype="DI" name="TestForceCoil8_S" textname="Тестовый регистр для force coil"/>
<item id="1018" mbs="1" mbreg="17" nbit="1" iotype="DI" name="TestForceCoil9_S" textname="Тестовый регистр для force coil"/>
<item id="1019" mbs="1" mbreg="17" nbit="2" iotype="DI" name="TestForceCoil10_S" textname="Тестовый регистр для force coil"/>
<item id="1020" mbs="1" mbreg="17" nbit="3" iotype="DI" name="TestForceCoil11_S" textname="Тестовый регистр для force coil"/>
<item id="1021" mbs="1" mbreg="17" nbit="4" iotype="DI" name="TestForceCoil12_S" textname="Тестовый регистр для force coil"/>
<item id="1022" mbs="1" mbreg="17" nbit="5" iotype="DI" name="TestForceCoil13_S" textname="Тестовый регистр для force coil"/>
<item id="1023" mbs="1" mbreg="17" nbit="6" iotype="DI" name="TestForceCoil14_S" textname="Тестовый регистр для force coil"/>
<item id="1024" mbs="1" mbreg="17" nbit="7" iotype="DI" name="TestForceCoil15_S" textname="Тестовый регистр для force coil"/>
<item id="1025" mbs="1" mbreg="18" iotype="AI" name="TestWrite10_S" textname="Тестовый регистр для 0x10"/>
<item id="1026" mbs="1" mbreg="19" iotype="AI" name="TestWrite10_S" textname="Тестовый регистр для 0x10"/>
<item id="1027" mbs="1" mbreg="20" iotype="DI" name="TestWrite10_S" textname="Тестовый регистр для 0x10"/>
<item id="1028" iotype="DI" name="TestWrite10_S" textname="Тестовый регистр для 0x10 (несуществующий)"/>
<!-- vtypes test -->
<item id="2001" mbs="1" mbreg="100" iotype="AI" vtype="I2" name="TestVtype1" textname="Тестовый регистр для проверки vtype"/>
<item id="2002" mbs="1" mbreg="102" iotype="AI" vtype="I2r" name="TestVtype2" textname="Тестовый регистр для проверки vtype"/>
<item id="2003" mbs="1" mbreg="104" iotype="AI" vtype="U2" name="TestVtype3" textname="Тестовый регистр для проверки vtype"/>
<item id="2004" mbs="1" mbreg="106" iotype="AI" vtype="U2r" name="TestVtype4" textname="Тестовый регистр для проверки vtype"/>
<item id="2005" mbs="1" mbreg="108" iotype="AI" vtype="byte" nbyte="1" name="TestVtype5" textname="Тестовый регистр для проверки vtype"/>
<item id="2006" mbs="1" mbreg="108" iotype="AI" vtype="byte" nbyte="2" name="TestVtype6" textname="Тестовый регистр для проверки vtype"/>
<item id="2007" mbs="1" mbreg="110" iotype="AI" vtype="F2" name="TestVtype7" textname="Тестовый регистр для проверки vtype"/>
<item id="2008" mbs="1" mbreg="112" iotype="AI" vtype="F2r" name="TestVtype8" textname="Тестовый регистр для проверки vtype"/>
<item id="2009" mbs="1" mbreg="110" iotype="AI" vtype="F2" name="TestVtype9" textname="Тестовый регистр для проверки vtype"/>
<item id="2010" mbs="1" mbreg="114" iotype="AI" vtype="F4" name="TestVtype10" textname="Тестовый регистр для проверки vtype"/>
<item id="2011" mbs="1" mbreg="118" iotype="AI" vtype="signed" name="TestVtype11" textname="Тестовый регистр для проверки vtype"/>
<item id="2012" mbs="1" mbreg="119" iotype="AI" vtype="unsigned" name="TestVtype12" textname="Тестовый регистр для проверки vtype"/>
<item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/> <item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/>
......
...@@ -8,249 +8,467 @@ ...@@ -8,249 +8,467 @@
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("Modbus Slave","[modbus]") static ModbusRTU::ModbusAddr slaveaddr = 0x01; // conf->getArgInt("--mbs-my-addr");
static int port = 20048; // conf->getArgInt("--mbs-inet-port");
static string addr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr");
static ObjectId slaveID = 6004; // conf->getObjectID( conf->getArgParam("--mbs-name"));
static ModbusTCPMaster* mb = nullptr;
static UInterface* ui = nullptr;
// -----------------------------------------------------------------------------
void InitTest()
{ {
CHECK( conf!=0 ); CHECK( conf!=0 );
ModbusRTU::ModbusAddr slaveaddr = 0x01; // conf->getArgInt("--mbs-my-addr"); if( ui == nullptr )
int port = 20048; // conf->getArgInt("--mbs-inet-port"); {
string addr("127.0.0.1"); // conf->getArgParam("--mbs-inet-addr"); ui = new UInterface();
ObjectId slaveID = 6004; // conf->getObjectID( conf->getArgParam("--mbs-name")); // UI понадобиться для проверки записанных в SM значений.
CHECK( ui->getObjectIndex() != 0 );
// UI понадобиться для проверки записанных в SM значений. CHECK( ui->getConf() == UniSetTypes::conf );
UInterface ui; CHECK( ui->waitReady(slaveID,5000) );
CHECK( ui.getObjectIndex() != 0 ); }
CHECK( ui.getConf() == UniSetTypes::conf );
CHECK( ui.waitReady(slaveID,5000) );
ModbusTCPMaster mb;
ost::InetAddress ia(addr.c_str());
mb.setTimeout(2000);
REQUIRE_NOTHROW( mb.connect(ia,port) );
if( mb == nullptr )
{
mb = new ModbusTCPMaster();
ost::InetAddress ia(addr.c_str());
mb->setTimeout(2000);
REQUIRE_NOTHROW( mb->connect(ia,port) );
}
}
// -----------------------------------------------------------------------------
#if 0 #if 0
SECTION("(0x01): read coil status") TEST_CASE("(0x01): read coil status","[modbus][mbslave][mbtcpslave]")
{
InitTest();
// read 1 bit
{ {
// read 1 bit ModbusRTU::ReadCoilRetMessage ret(slaveaddr);
{ REQUIRE_NOTHROW( ret = mb->read01(slaveaddr,1000,1) );
ModbusRTU::ReadCoilRetMessage ret(slaveaddr); ModbusRTU::DataBits b(ret.data[0]);
REQUIRE_NOTHROW( ret = mb.read01(slaveaddr,1000,1) ); REQUIRE( b[0] == 1 );
ModbusRTU::DataBits b(ret.data[0]); }
REQUIRE( b[0] == 1 ); // read 3 bit
} {
// read 3 bit ModbusRTU::ReadCoilRetMessage ret(slaveaddr);
{ REQUIRE_NOTHROW( ret = mb->read01(slaveaddr,1000,3) );
ModbusRTU::ReadCoilRetMessage ret(slaveaddr); ModbusRTU::DataBits b(ret.data[0]);
REQUIRE_NOTHROW( ret = mb.read01(slaveaddr,1000,3) ); REQUIRE( b[0] == 1 );
ModbusRTU::DataBits b(ret.data[0]); REQUIRE( b[1] == 1 );
REQUIRE( b[0] == 1 ); REQUIRE( b[2] == 0 );
REQUIRE( b[1] == 1 ); }
REQUIRE( b[2] == 0 ); }
}
TEST_CASE("(0x02): read input status","[modbus][mbslave][mbtcpslave]")
{
InitTest();
SECTION("read 1 bit")
{
ModbusRTU::ReadInputStatusRetMessage ret(slaveaddr);
REQUIRE_NOTHROW( ret = mb->read02(slaveaddr,1000,1) );
ModbusRTU::DataBits b(ret.data[0]);
REQUIRE( b[0] == 1 );
}
SECTION("read 3 bit")
{
ModbusRTU::ReadInputStatusRetMessage ret(slaveaddr);
REQUIRE_NOTHROW( ret = mb->read02(slaveaddr,1000,3) );
ModbusRTU::DataBits b(ret.data[0]);
REQUIRE( b[0] == 1 );
REQUIRE( b[1] == 1 );
REQUIRE( b[2] == 0 );
} }
}
#endif #endif
#if 0
SECTION("(0x02): read input status") TEST_CASE("Function (0x03): 'read register outputs or memories or read word outputs or memories'","[modbus][mbslave][mbtcpslave]")
{
InitTest();
ModbusRTU::ModbusData tREG=10;
SECTION("Test: read one reg..")
{ {
// read 1 bit ModbusRTU::ReadOutputRetMessage ret = mb->read03(slaveaddr,tREG,1);
REQUIRE( ret.data[0] == 10 );
}
SECTION("Test: read many registers..")
{
ModbusRTU::ReadOutputRetMessage ret = mb->read03(slaveaddr,tREG,3);
REQUIRE( ret.data[0] == 10 );
REQUIRE( ret.data[1] == 11 );
REQUIRE( (signed short)(ret.data[2]) == -10 );
}
SECTION("Test: read MAXDATA count..")
{
ModbusRTU::ReadOutputRetMessage ret = mb->read03(slaveaddr,tREG,ModbusRTU::MAXDATALEN);
REQUIRE( ret.count == ModbusRTU::MAXDATALEN );
}
SECTION("Test: read TOO many registers")
{
try
{ {
ModbusRTU::ReadInputStatusRetMessage ret(slaveaddr); mb->read03(slaveaddr,-23,1200);
REQUIRE_NOTHROW( ret = mb.read02(slaveaddr,1000,1) );
ModbusRTU::DataBits b(ret.data[0]);
REQUIRE( b[0] == 1 );
} }
// read 3 bit catch( ModbusRTU::mbException& ex )
{ {
ModbusRTU::ReadInputStatusRetMessage ret(slaveaddr); REQUIRE( ex.err == ModbusRTU::erTimeOut );
REQUIRE_NOTHROW( ret = mb.read02(slaveaddr,1000,3) );
ModbusRTU::DataBits b(ret.data[0]);
REQUIRE( b[0] == 1 );
REQUIRE( b[1] == 1 );
REQUIRE( b[2] == 0 );
} }
} }
#endif SECTION("Test: read unknown registers")
SECTION("Function (0x03): 'read register outputs or memories or read word outputs or memories'")
{ {
SECTION("Test: read one reg..") try
{ {
ModbusRTU::ReadOutputRetMessage ret = mb.read03(slaveaddr,10,1); mb->read03(slaveaddr,-23,1);
REQUIRE( ret.data[0] == 10 );
} }
SECTION("Test: read many registers..") catch( ModbusRTU::mbException& ex )
{ {
ModbusRTU::ReadOutputRetMessage ret = mb.read03(slaveaddr,10,3); REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
REQUIRE( ret.data[0] == 10 );
REQUIRE( ret.data[1] == 11 );
REQUIRE( (signed short)(ret.data[2]) == -10 );
} }
SECTION("Test: read MAXDATA count..") }
SECTION("Test: incorrect number")
{
try
{ {
ModbusRTU::ReadOutputRetMessage ret = mb.read03(slaveaddr,10,ModbusRTU::MAXDATALEN); mb->read03(slaveaddr,tREG,-3);
REQUIRE( ret.count == ModbusRTU::MAXDATALEN );
} }
SECTION("Test: read TOO many registers") catch( ModbusRTU::mbException& ex )
{ {
try REQUIRE( ex.err == ModbusRTU::erTimeOut );
{
mb.read03(slaveaddr,-23,1200);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erTimeOut );
}
} }
SECTION("Test: read unknown registers") }
SECTION("Test: zero number")
{
try
{ {
try mb->read03(slaveaddr,tREG,0);
{
mb.read03(slaveaddr,-23,1);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
}
} }
SECTION("Test: incorrect number") catch( ModbusRTU::mbException& ex )
{ {
try REQUIRE( ex.err == ModbusRTU::erTimeOut );
{
mb.read03(slaveaddr,10,-3);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erTimeOut );
}
} }
} }
}
SECTION("Function (0x04): 'read input registers or memories or read word outputs or memories'") TEST_CASE("Function (0x04): 'read input registers or memories or read word outputs or memories'","[modbus][mbslave][mbtcpslave]")
{
InitTest();
ModbusRTU::ModbusData tREG=10;
SECTION("Test: read one reg..")
{ {
SECTION("Test: read one reg..") ModbusRTU::ReadInputRetMessage ret = mb->read04(slaveaddr,tREG,1);
{ REQUIRE( ret.data[0] == 10 );
ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr,10,1); }
REQUIRE( ret.data[0] == 10 ); SECTION("Test: read one reg..")
} {
SECTION("Test: read one reg..") ModbusRTU::ReadInputRetMessage ret = mb->read04(slaveaddr,tREG,1);
REQUIRE( ret.data[0] == 10 );
}
SECTION("Test: read many registers..")
{
ModbusRTU::ReadInputRetMessage ret = mb->read04(slaveaddr,tREG,4);
REQUIRE( ret.data[0] == 10 );
REQUIRE( ret.data[1] == 11 );
REQUIRE( (signed short)(ret.data[2]) == -10 );
REQUIRE( (signed short)(ret.data[3]) == -10000 );
}
SECTION("Test: read MAXDATA count..")
{
ModbusRTU::ReadInputRetMessage ret = mb->read04(slaveaddr,tREG,ModbusRTU::MAXDATALEN);
REQUIRE( ret.count == ModbusRTU::MAXDATALEN );
}
SECTION("Test: read TOO many registers")
{
try
{ {
ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr,10,1); mb->read04(slaveaddr,-23,1200);
REQUIRE( ret.data[0] == 10 );
} }
SECTION("Test: read many registers..") catch( ModbusRTU::mbException& ex )
{ {
ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr,10,4); REQUIRE( ex.err == ModbusRTU::erTimeOut );
REQUIRE( ret.data[0] == 10 );
REQUIRE( ret.data[1] == 11 );
REQUIRE( (signed short)(ret.data[2]) == -10 );
REQUIRE( (signed short)(ret.data[3]) == -10000 );
} }
SECTION("Test: read MAXDATA count..") }
SECTION("Test: read unknown registers")
{
try
{ {
ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr,10,ModbusRTU::MAXDATALEN); mb->read04(slaveaddr,-23,1);
REQUIRE( ret.count == ModbusRTU::MAXDATALEN );
} }
SECTION("Test: read TOO many registers") catch( ModbusRTU::mbException& ex )
{ {
try REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
{
mb.read04(slaveaddr,-23,1200);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erTimeOut );
}
} }
SECTION("Test: read unknown registers") }
SECTION("Test: incorrect number")
{
try
{ {
try mb->read04(slaveaddr,tREG,-3);
{
mb.read04(slaveaddr,-23,1);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
}
} }
SECTION("Test: incorrect number") catch( ModbusRTU::mbException& ex )
{ {
try REQUIRE( ex.err == ModbusRTU::erTimeOut );
{
mb.read04(slaveaddr,10,-3);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erTimeOut );
}
} }
} }
SECTION("(0x05): forces a single coil to either ON or OFF") SECTION("Test: zero number")
{ {
ObjectId tID = 1007; try
SECTION("Test: ON")
{ {
ModbusRTU::ForceSingleCoilRetMessage ret = mb.write05(slaveaddr,14,true); mb->read04(slaveaddr,tREG,0);
CHECK( ret.start == 14 );
CHECK( ret.cmd() == true );
CHECK( ui.getValue(tID) == 1 );
} }
SECTION("Test: OFF") catch( ModbusRTU::mbException& ex )
{ {
ModbusRTU::ForceSingleCoilRetMessage ret = mb.write05(slaveaddr,14,false); REQUIRE( ex.err == ModbusRTU::erTimeOut );
CHECK( ret.start == 14 );
CHECK( ret.cmd() == false );
CHECK( ui.getValue(tID) == 0 );
} }
} }
#if 0 }
SECTION("(0x06): write register outputs or memories")
TEST_CASE("(0x05): forces a single coil to either ON or OFF","[modbus][mbslave][mbtcpslave]")
{
InitTest();
ObjectId tID = 1007;
ModbusRTU::ModbusData tREG=14;
SECTION("Test: ON")
{ {
ModbusRTU::ForceSingleCoilRetMessage ret = mb->write05(slaveaddr,tREG,true);
CHECK( ret.start == tREG );
CHECK( ret.cmd() == true );
CHECK( ui->getValue(tID) == 1 );
}
SECTION("Test: OFF")
{
ModbusRTU::ForceSingleCoilRetMessage ret = mb->write05(slaveaddr,tREG,false);
CHECK( ret.start == tREG );
CHECK( ret.cmd() == false );
CHECK( ui->getValue(tID) == 0 );
}
}
TEST_CASE("(0x06): write register outputs or memories","[modbus][mbslave][mbtcpslave]")
{
InitTest();
ObjectId tID = 1008;
ModbusRTU::ModbusData tREG=15;
SECTION("Test: write register")
{
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(slaveaddr,tREG,10);
REQUIRE( ret.start == tREG );
REQUIRE( ret.data == 10 );
REQUIRE( ui->getValue(tID) == 10 );
}
SECTION("Test: write negative value")
{
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(slaveaddr,tREG,-10);
REQUIRE( ret.start == tREG );
REQUIRE( (signed short)ret.data == -10 );
REQUIRE( (signed short)ui->getValue(tID) == -10 );
} }
SECTION("Test: write zero value")
{
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(slaveaddr,tREG,0);
REQUIRE( ret.start == tREG );
REQUIRE( ret.data == 0 );
REQUIRE( ui->getValue(tID) == 0 );
}
SECTION("Test: write OVERFLOW VALUE")
{
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 #endif
}
SECTION("Test: write unknown register")
{
try
{
mb->write06(slaveaddr,-23,10);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
}
}
}
#if 0 #if 0
SECTION("(0x08): Diagnostics (Serial Line only)") SECTION("(0x08): Diagnostics (Serial Line only)")
{ {
} }
#endif #endif
#if 0 #if 0
SECTION("(0x0F): force multiple coils") \TODO Переписать реализацию MBSlave... ввести понятие nbit.
TEST_CASE("(0x0F): force multiple coils","[modbus][mbslave][mbtcpslave]")
{
WARN("FIXME: 'force coil status'. Use 'nbit'?"):
InitTest();
ObjectId tID = 1009;
ModbusRTU::ModbusData tREG=16;
SECTION("Test: write 2 bit to 1")
{ {
ModbusRTU::ForceCoilsMessage msg(slaveaddr,tREG);
ModbusRTU::DataBits b(3);
msg.addData(b);
ModbusRTU::ForceCoilsRetMessage ret = mb->write0F(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 8 );
REQUIRE( ui->getValue(tID) == 1 );
REQUIRE( ui->getValue(tID+1) == 1 );
} }
SECTION("(0x10): write register outputs or memories") SECTION("Test: write 2 bit to 0")
{ {
ModbusRTU::ForceCoilsMessage msg(slaveaddr,tREG);
ModbusRTU::DataBits b(0);
msg.addData(b);
ModbusRTU::ForceCoilsRetMessage ret = mb->write0F(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 8 );
REQUIRE( ui->getValue(tID) == 0 );
REQUIRE( ui->getValue(tID+1) == 0 );
} }
}
#endif #endif
#if 0 TEST_CASE("(0x10): write register outputs or memories","[modbus][mbslave][mbtcpslave]")
SECTION("(0x10): write register outputs or memories") {
InitTest();
InitTest();
ObjectId tID = 1025;
ModbusRTU::ModbusData tREG=18;
SECTION("Test: write one register")
{ {
fnReadFileRecord = 0x14, /*!< read file record */ 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 );
} }
SECTION("(0x10): write register outputs or memories") SECTION("Test: write 3 register")
{ {
fnWriteFileRecord = 0x15, /*!< write file record */ ModbusRTU::WriteOutputMessage msg(slaveaddr,tREG);
msg.addData(10);
msg.addData(11);
msg.addData(12);
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 3 );
REQUIRE( ui->getValue(tID) == 10 );
REQUIRE( ui->getValue(tID+1) == 11 );
REQUIRE( ui->getValue(tID+2) == 1 ); // 1 - т.к. это "DI"
} }
SECTION("(0x10): write register outputs or memories") SECTION("Test: write negative value")
{ {
fnMEI = 0x2B, /*!< Modbus Encapsulated Interface */ ModbusRTU::WriteOutputMessage msg(slaveaddr,tREG);
msg.addData(-10);
msg.addData(-100);
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == 2 );
REQUIRE( (signed short)ui->getValue(tID) == -10 );
REQUIRE( (signed short)ui->getValue(tID+1) == -100 );
} }
SECTION("(0x10): write register outputs or memories") SECTION("Test: write zero registers")
{ {
fnSetDateTime = 0x50, /*!< set date and time */ 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 );
}
SECTION("Test: write OVERFLOW VALUE")
{
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
} }
SECTION("(0x10): write register outputs or memories") SECTION("Test: write 2 good registers and unknown register")
{ {
fnRemoteService = 0x53, /*!< call remote service */ 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 );
} }
SECTION("(0x10): write register outputs or memories") SECTION("Test: write ALL unknown registers")
{ {
fnJournalCommand = 0x65, /*!< read,write,delete alarm journal */ ModbusRTU::WriteOutputMessage msg(slaveaddr,tREG+20000);
msg.addData(10);
msg.addData(11);
msg.addData(12);
try
{
mb->write10(msg);
}
catch( ModbusRTU::mbException& ex )
{
REQUIRE( ex.err == ModbusRTU::erBadDataAddress );
}
} }
SECTION("(0x10): write register outputs or memories") SECTION("Test: limit the amount of data verification")
{ {
fnFileTransfer = 0x66 /*!< file transfer */ ModbusRTU::WriteOutputMessage msg(slaveaddr,tREG);
for( int i=0; i<ModbusRTU::MAXDATALEN; i++ )
msg.addData(10+i);
CHECK_FALSE( msg.isFull() );
msg.addData(1);
CHECK( msg.isFull() );
} }
#endif
} }
TEST_CASE("Read(0x03,0x04): vtypes..","[modbus][mbslave][mbtcpslave]")
{
InitTest();
}
TEST_CASE("Write(0x10): vtypes..","[modbus][mbslave][mbtcpslave]")
{
InitTest();
}
#if 0
TEST_CASE("(0x14): read file record","[modbus][mbslave][mbtcpslave]")
{
}
TEST_CASE("(0x15): write file record","[modbus][mbslave][mbtcpslave]")
{
}
TEST_CASE("(0x2B): Modbus Encapsulated Interface","[modbus][mbslave][mbtcpslave]")
{
}
TEST_CASE("(0x50): set date and time")
{
}
TEST_CASE("(0x53): call remote service")
{
}
TEST_CASE("(0x65): read,write,delete alarm journal")
{
}
TEST_CASE("(0x66): file transfer")
{
}
#endif
...@@ -208,6 +208,7 @@ namespace ModbusRTU ...@@ -208,6 +208,7 @@ namespace ModbusRTU
ModbusByte mbyte(); ModbusByte mbyte();
bool operator[]( const size_t i ){ return b[i]; } bool operator[]( const size_t i ){ return b[i]; }
void set( int n, bool s ){ b.set(n,s); }
std::bitset<BitsPerByte> b; std::bitset<BitsPerByte> b;
}; };
...@@ -620,13 +621,13 @@ namespace ModbusRTU ...@@ -620,13 +621,13 @@ namespace ModbusRTU
* \return FALSE - если НЕ удалось * \return FALSE - если НЕ удалось
*/ */
bool addData( DataBits d ); bool addData( DataBits d );
// return number of bit // return number of bit
// -1 - error // -1 - error
int addBit( bool state ); int addBit( bool state );
bool setBit( int nbit, bool state ); bool setBit( int nbit, bool state );
inline int last(){ return quant; } inline int last(){ return quant; }
/*! получение данных. /*! получение данных.
...@@ -636,7 +637,7 @@ namespace ModbusRTU ...@@ -636,7 +637,7 @@ namespace ModbusRTU
* \return FALSE - если НЕ найдено * \return FALSE - если НЕ найдено
*/ */
bool getData( unsigned char dnum, DataBits& d ); bool getData( unsigned char dnum, DataBits& d );
bool getBit( unsigned char bnum ); bool getBit( unsigned char bnum );
void clear(); void clear();
...@@ -730,7 +731,7 @@ namespace ModbusRTU ...@@ -730,7 +731,7 @@ namespace ModbusRTU
bool addData( ModbusData d ); bool addData( ModbusData d );
void clear(); void clear();
inline bool isFull() inline bool isFull()
{ {
return ( quant*sizeof(ModbusData) >= MAXLENPACKET ); return ( quant*sizeof(ModbusData) >= MAXLENPACKET );
} }
...@@ -947,7 +948,7 @@ namespace ModbusRTU ...@@ -947,7 +948,7 @@ namespace ModbusRTU
public ModbusHeader public ModbusHeader
{ {
ModbusData start; /*!< записанный начальный адрес */ ModbusData start; /*!< записанный начальный адрес */
ModbusData data; /*!< записанный начальный адрес */ ModbusData data; /*!< записанные данные */
ModbusCRC crc; ModbusCRC crc;
......
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