Commit 56392381 authored by Pavel Vainerman's avatar Pavel Vainerman

(Modbus): исправил ошибки в обработке ошибок обмена,

небольшой рефакторинг типов, добавил вспомогательную функция (numBytes).
parent 23c18175
......@@ -119,12 +119,9 @@ ModbusRTU::mbErrCode MBSlave::readCoilStatus( ReadCoilMessage& query,
d.b[6] = 1;
// Фомирование ответа:
unsigned int bcnt = query.count / ModbusRTU::BitsPerByte;
size_t bcnt = ModbusRTU::numBytes(query.count);
if( (query.count % ModbusRTU::BitsPerByte) > 0 )
bcnt++;
for( unsigned int i = 0; i < bcnt; i++ )
for( size_t i = 0; i < bcnt; i++ )
{
if( replyVal != -1 )
reply.addData(replyVal);
......@@ -163,12 +160,9 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query,
}
else
{
unsigned int bcnt = query.count / ModbusRTU::BitsPerByte;
if( (query.count % ModbusRTU::BitsPerByte) > 0 )
bcnt++;
size_t bcnt = ModbusRTU::numBytes(query.count);
for( unsigned int i = 0; i < bcnt; i++ )
for( size_t i = 0; i < bcnt; i++ )
{
if( i == 1 )
reply.addData(replyVal2);
......
......@@ -155,12 +155,10 @@ ModbusRTU::mbErrCode MBTCPServer::readInputStatus( ReadInputStatusMessage& query
}
else
{
int bcnt = query.count / ModbusRTU::BitsPerByte;
if( (query.count % ModbusRTU::BitsPerByte) > 0 )
bcnt++;
size_t bcnt = ModbusRTU::numBytes(query.count);
for( auto i = 0; i < bcnt; i++ )
for( size_t i = 0; i < bcnt; i++ )
reply.addData(replyVal);
}
......
......@@ -712,7 +712,7 @@ int main( int argc, char** argv )
tofile = s.str();
}
mb.fileTransfer( slaveaddr, reg, tofile.c_str(), tout);
mb.fileTransfer( slaveaddr, reg, tofile, tout);
}
break;
......
......@@ -121,6 +121,13 @@ ModbusRTU::mbErrCode MBTCPTestServer::readCoilStatus( ReadCoilMessage& query,
d.b[4] = 1;
d.b[6] = 1;
if( query.count == 0 )
{
if( verbose )
cout << "(readCoilStatus): ERROR qount=0" << endl;
return ModbusRTU::erBadDataValue;
}
if( query.count <= 1 )
{
if( replyVal != std::numeric_limits<uint32_t>::max() )
......@@ -132,10 +139,10 @@ ModbusRTU::mbErrCode MBTCPTestServer::readCoilStatus( ReadCoilMessage& query,
}
// Фомирование ответа:
int num = 0; // добавленное количество данных
ModbusData reg = query.start;
ModbusData num = 0; // добавленное количество данных
size_t bcnt = numBytes(query.count);
for( ; num < query.count; num++, reg++ )
for( ; num < bcnt; num++ )
{
if( replyVal != std::numeric_limits<uint32_t>::max() )
reply.addData(replyVal);
......@@ -143,14 +150,6 @@ ModbusRTU::mbErrCode MBTCPTestServer::readCoilStatus( ReadCoilMessage& query,
reply.addData(d);
}
// Если мы в начале проверили, что запрос входит в разрешёный диапазон
// то теоретически этой ситуации возникнуть не может...
if( reply.bcnt < query.count )
{
cerr << "(readCoilStatus): Получили меньше чем ожидали. "
<< " Запросили " << query.count << " получили " << reply.bcnt << endl;
}
return ModbusRTU::erNoError;
}
// -------------------------------------------------------------------------
......@@ -168,6 +167,13 @@ ModbusRTU::mbErrCode MBTCPTestServer::readInputStatus( ReadInputStatusMessage& q
d.b[3] = 1;
d.b[7] = 1;
if( query.count == 0 )
{
if( verbose )
cout << "(readInputStatus): ERROR qount=0" << endl;
return ModbusRTU::erBadDataValue;
}
if( replyVal == std::numeric_limits<uint32_t>::max() )
{
size_t bnum = 0;
......@@ -185,10 +191,7 @@ ModbusRTU::mbErrCode MBTCPTestServer::readInputStatus( ReadInputStatusMessage& q
}
else
{
size_t bcnt = query.count / ModbusRTU::BitsPerByte;
if( (query.count % ModbusRTU::BitsPerByte) > 0 )
bcnt++;
size_t bcnt = ModbusRTU::numBytes(query.count);
for( size_t i = 0; i < bcnt; i++ )
reply.addData(replyVal);
......
......@@ -15,7 +15,7 @@ cd -
--mbtcp-filter-value 1 \
--mbtcp-gateway-iaddr localhost \
--mbtcp-gateway-port 20048 \
--mbtcp-polltime 50 --mbtcp-recv-timeout 500
--mbtcp-polltime 50 --mbtcp-recv-timeout 500
#--mbtcp-log-add-levels any
#--mbtcp-default-mbinit-ok 1
#--dlog-add-levels any
......
......@@ -71,7 +71,7 @@ static void InitTest()
throw;
}
//mbs->setVerbose(true);
// mbs->setVerbose(true);
CHECK( mbs != nullptr );
mbs->execute();
......
......@@ -132,7 +132,7 @@ namespace uniset
\param part_timeout_msec - таймаут на получение очередной части файла.
*/
void fileTransfer( ModbusRTU::ModbusAddr addr, ModbusRTU::ModbusData idFile,
const char* save2filename, timeout_t part_timeout_msec = 2000 )
const std::string& save2filename, timeout_t part_timeout_msec = 2000 )
throw(ModbusRTU::mbException);
// ---------------------------------------------------------------------
......
......@@ -151,6 +151,7 @@ namespace uniset
std::string b2str( const ModbusByte b );
// -------------------------------------------------------------------------
float dat2f( const ModbusData dat1, const ModbusData dat2 );
size_t numBytes( const size_t nbits ); // сколько байт нужно для указанного количества бит
// -------------------------------------------------------------------------
bool isWriteFunction( SlaveFunctionCode c );
bool isReadFunction( SlaveFunctionCode c );
......@@ -392,7 +393,7 @@ namespace uniset
* \return TRUE - если есть
* \return FALSE - если НЕ найдено
*/
bool setBit( unsigned char dnum, unsigned char bnum, bool state );
bool setBit( uint8_t dnum, uint8_t bnum, bool state );
/*! получение данных.
* \param bnum - номер байта(0..MAXLENPACKET)
......@@ -400,7 +401,7 @@ namespace uniset
* \return TRUE - если есть
* \return FALSE - если НЕ найдено
*/
bool getData( unsigned char bnum, DataBits& d ) const;
bool getData( uint8_t bnum, DataBits& d ) const;
/*! очистка данных */
void clear();
......@@ -492,7 +493,7 @@ namespace uniset
* \return TRUE - если есть
* \return FALSE - если НЕ найдено
*/
bool setBit( unsigned char dnum, unsigned char bnum, bool state );
bool setBit( uint8_t dnum, uint8_t bnum, bool state );
/*! получение данных.
* \param dnum - номер байта (0..MAXLENPACKET)
......@@ -500,7 +501,7 @@ namespace uniset
* \return TRUE - если есть
* \return FALSE - если НЕ найдено
*/
bool getData( unsigned char dnum, DataBits& d ) const;
bool getData( uint8_t dnum, DataBits& d ) const;
/*! очистка данных */
void clear();
......@@ -727,7 +728,7 @@ namespace uniset
// -1 - error
int addBit( bool state );
bool setBit( int nbit, bool state );
bool setBit( uint8_t nbit, bool state );
inline size_t last() const
{
......@@ -740,9 +741,7 @@ namespace uniset
* \return TRUE - если есть
* \return FALSE - если НЕ найдено
*/
bool getData( unsigned char dnum, DataBits& d );
bool getBit( unsigned char bnum );
bool getData( uint8_t dnum, DataBits& d );
void clear();
inline bool isFull() const
......
......@@ -69,7 +69,7 @@ namespace uniset
{
ReadCoilRetMessage ret(qreply);
if( ret.bcnt != (count*2) )
if( ret.bcnt != numBytes(count) )
throw mbException(erBadDataValue);
return ret;
......@@ -90,7 +90,7 @@ namespace uniset
{
ReadInputStatusRetMessage ret(qreply);
if( ret.bcnt != (count*2) )
if( ret.bcnt != numBytes(count) )
throw mbException(erBadDataValue);
return ret;
......@@ -309,15 +309,15 @@ namespace uniset
throw mbException(res);
}
// --------------------------------------------------------------------------------
void ModbusClient::fileTransfer( ModbusAddr addr, ModbusData numfile,
const char* save2filename, timeout_t part_timeout_msec )
void ModbusClient::fileTransfer(ModbusAddr addr, ModbusData numfile,
const std::string& save2filename, timeout_t part_timeout_msec )
throw(ModbusRTU::mbException)
{
//#warning Необходимо реализовать
// throw mbException(erUnExpectedPacketType);
mbErrCode res = erNoError;
FILE* fdsave = fopen(save2filename, "w");
FILE* fdsave = fopen(save2filename.c_str(), "w");
if( fdsave == NULL )
{
......@@ -329,8 +329,8 @@ namespace uniset
throw mbException(erHardwareError);
}
unsigned short maxpackets = 65535;
unsigned short curpack = 0;
uint16_t maxpackets = 65535;
uint16_t curpack = 0;
PassiveTimer ptTimeout(part_timeout_msec);
......
......@@ -474,7 +474,7 @@ namespace uniset
{
ModbusByte ubyte = 0;
for( unsigned int i = 0; i < b.size(); i++ )
for( size_t i = 0; i < b.size(); i++ )
{
if( b[i] )
ubyte |= 1 << i;
......@@ -485,7 +485,7 @@ namespace uniset
// -------------------------------------------------------------------------
const DataBits& DataBits::operator=( const ModbusByte& r )
{
for( unsigned int i = 0; i < b.size(); i++ )
for( size_t i = 0; i < b.size(); i++ )
b[i] = r & (1 << i);
return (*this);
......@@ -495,7 +495,7 @@ namespace uniset
{
os << "[";
for( int i = d.b.size() - 1; i >= 0; i-- )
for( size_t i = d.b.size() - 1; i >= 0; i-- )
os << d.b[i];
os << "]";
......@@ -533,7 +533,7 @@ namespace uniset
{
ModbusData udata = 0;
for( unsigned int i = 0; i < b.size(); i++ )
for( size_t i = 0; i < b.size(); i++ )
{
if( b[i] )
udata |= 1 << i;
......@@ -546,7 +546,7 @@ namespace uniset
{
const size_t sz = b.size();
for( unsigned int i = 0; i < sz; i++ )
for( size_t i = 0; i < sz; i++ )
b[i] = r & (1 << i);
return (*this);
......@@ -556,7 +556,7 @@ namespace uniset
{
os << "[";
for( int i = d.b.size() - 1; i >= 0; i-- )
for( size_t i = d.b.size() - 1; i >= 0; i-- )
os << d.b[i];
os << "]";
......@@ -613,7 +613,7 @@ namespace uniset
memset(data, 0, sizeof(data));
}
// -------------------------------------------------------------------------
bool ReadCoilRetMessage::setBit( unsigned char dnum, unsigned char bnum, bool state )
bool ReadCoilRetMessage::setBit( uint8_t dnum, uint8_t bnum, bool state )
{
if( dnum < bcnt && bnum < BitsPerByte )
{
......@@ -635,7 +635,7 @@ namespace uniset
return true;
}
// -------------------------------------------------------------------------
bool ReadCoilRetMessage::getData( unsigned char dnum, DataBits& d ) const
bool ReadCoilRetMessage::getData( uint8_t dnum, DataBits& d ) const
{
if( dnum < bcnt )
{
......@@ -656,7 +656,7 @@ namespace uniset
{
ModbusMessage mm;
// assert(sizeof(ModbusMessage)>=sizeof(ReadCoilRetMessage));
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
// копируем заголовок и данные
memcpy(&mm.pduhead, this, szModbusHeader);
......@@ -814,7 +814,7 @@ namespace uniset
memset(data, 0, sizeof(data));
}
// -------------------------------------------------------------------------
bool ReadInputStatusRetMessage::setBit( unsigned char dnum, unsigned char bnum, bool state )
bool ReadInputStatusRetMessage::setBit( uint8_t dnum, uint8_t bnum, bool state )
{
if( dnum < bcnt && bnum < BitsPerByte )
{
......@@ -836,7 +836,7 @@ namespace uniset
return true;
}
// -------------------------------------------------------------------------
bool ReadInputStatusRetMessage::getData( unsigned char dnum, DataBits& d ) const
bool ReadInputStatusRetMessage::getData( uint8_t dnum, DataBits& d ) const
{
if( dnum < bcnt )
{
......@@ -857,7 +857,7 @@ namespace uniset
{
ModbusMessage mm;
// assert(sizeof(ModbusMessage)>=sizeof(ReadCoilRetMessage));
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
// копируем заголовок и данные
memcpy(&mm.pduhead, this, szModbusHeader);
......@@ -1005,7 +1005,7 @@ namespace uniset
memcpy(&data, &(m.data[1]), bcnt);
// переворачиваем данные
for( unsigned int i = 0; i < cnt; i++ )
for( size_t i = 0; i < cnt; i++ )
data[i] = SWAPSHORT(data[i]);
memcpy(&crc, &(m.data[bcnt + 1]), szCRC);
......@@ -1049,7 +1049,7 @@ namespace uniset
{
ModbusMessage mm;
// assert(sizeof(ModbusMessage)>=sizeof(ReadOutputRetMessage));
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
// копируем заголовок и данные
memcpy(&mm.pduhead, this, szModbusHeader);
......@@ -1264,7 +1264,7 @@ namespace uniset
ModbusMessage ReadInputRetMessage::transport_msg()
{
ModbusMessage mm;
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
// копируем заголовок и данные
memcpy(&mm.pduhead, this, szModbusHeader);
......@@ -1343,7 +1343,7 @@ namespace uniset
// -------------------------------------------------------------------------
int ForceCoilsMessage::addBit( bool state )
{
int qnum = quant % BitsPerByte;
size_t qnum = quant % BitsPerByte;
if( qnum == 0 )
bcnt++;
......@@ -1355,13 +1355,13 @@ namespace uniset
return (quant - 1);
}
// -------------------------------------------------------------------------
bool ForceCoilsMessage::setBit( int nbit, bool state )
bool ForceCoilsMessage::setBit( uint8_t nbit, bool state )
{
if( nbit < 0 || nbit >= quant )
return false;
int bnum = nbit / BitsPerByte;
int qnum = nbit % BitsPerByte;
size_t bnum = nbit / BitsPerByte;
size_t qnum = nbit % BitsPerByte;
DataBits b(data[bnum]);
b.b[qnum] = state;
......@@ -1369,7 +1369,7 @@ namespace uniset
return true;
}
// -------------------------------------------------------------------------
bool ForceCoilsMessage::getData( unsigned char dnum, DataBits& d )
bool ForceCoilsMessage::getData( uint8_t dnum, DataBits& d )
{
if( dnum < bcnt )
{
......@@ -1390,7 +1390,7 @@ namespace uniset
// -------------------------------------------------------------------------
ModbusMessage ForceCoilsMessage::transport_msg()
{
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
ModbusMessage mm;
// копируем заголовок
......@@ -1625,7 +1625,7 @@ namespace uniset
// -------------------------------------------------------------------------
ModbusMessage WriteOutputMessage::transport_msg()
{
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
ModbusMessage mm;
// копируем заголовок
......@@ -2343,7 +2343,7 @@ namespace uniset
{
ModbusMessage mm;
// assert(sizeof(ModbusMessage)>=sizeof(DiagnosticMessage));
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
// копируем заголовок и данные
memcpy(&mm.pduhead, this, szModbusHeader);
......@@ -2456,7 +2456,7 @@ namespace uniset
// -------------------------------------------------------------------------
ModbusMessage MEIMessageRDI::transport_msg()
{
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
ModbusMessage mm;
// копируем заголовок
......@@ -2679,7 +2679,7 @@ namespace uniset
ModbusMessage MEIMessageRetRDI::transport_msg()
{
ModbusMessage mm;
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
// копируем заголовок и данные
memcpy(&mm.pduhead, this, szModbusHeader);
......@@ -2820,7 +2820,7 @@ namespace uniset
// копируем
memcpy( data, buf, len );
count = len / sizeof(ModbusData);
count = len / sizeof(ModbusData);
// выравниваем до границы слова..
if( len % sizeof(ModbusData) )
......@@ -2841,7 +2841,7 @@ namespace uniset
{
ModbusMessage mm;
// assert(sizeof(ModbusMessage)>=sizeof(ReadOutputRetMessage));
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader + szData() );
assert( sizeof(ModbusMessage) >= szModbusHeader + szData() );
// копируем заголовок и данные
memcpy(&mm.pduhead, this, szModbusHeader);
......@@ -2961,14 +2961,14 @@ namespace uniset
std::string ModbusRTU::addr2str( const ModbusAddr addr )
{
ostringstream s;
s << "0x" << hex << setfill('0') << setw(2) << (unsigned short)addr;
s << "0x" << hex << setfill('0') << setw(2) << (int)addr;
return s.str();
}
// -------------------------------------------------------------------------
std::string ModbusRTU::b2str( const ModbusByte b )
{
ostringstream s;
s << hex << setfill('0') << setw(2) << (unsigned short)b;
s << hex << setfill('0') << setw(2) << (int)b;
return s.str();
}
// -------------------------------------------------------------------------
......@@ -3634,7 +3634,7 @@ namespace uniset
s << id;
return s.str();
}
// -----------------------------------------------------------------------
// ----------------------------------------------------------------------
ModbusRTU::RegID ModbusRTU::genRegID( const ModbusRTU::ModbusData mbreg, const int fn )
{
// диапазоны:
......@@ -3646,5 +3646,20 @@ namespace uniset
// fn необходимо привести к диапазону 0..max
return max + mbreg + max + uniset::lcalibrate(fn, 0, fn_max, 0, max, false);
}
// ----------------------------------------------------------------------
size_t ModbusRTU::numBytes( const size_t nbits )
{
if( nbits == 0 )
return 0;
if( nbits < ModbusRTU::BitsPerByte )
return 1;
size_t bcnt = ( nbits / ModbusRTU::BitsPerByte );
if( nbits % BitsPerByte )
bcnt++;
return bcnt;
}
// -----------------------------------------------------------------------
} // end of namespace uniset
......@@ -112,6 +112,19 @@ TEST_CASE("checkCRC", "[modbus][checkCRC]" )
// ModbusCRC checkCRC( ModbusByte* start, int len );
}
// ---------------------------------------------------------------
TEST_CASE("numBytes function", "[modbus][numbytes]" )
{
REQUIRE( ModbusRTU::numBytes(0) == 0 );
REQUIRE( ModbusRTU::numBytes(1) == 1 );
REQUIRE( ModbusRTU::numBytes(8) == 1 );
REQUIRE( ModbusRTU::numBytes(10) == 2 );
REQUIRE( ModbusRTU::numBytes(16) == 2 );
REQUIRE( ModbusRTU::numBytes(256) == 32 );
REQUIRE( ModbusRTU::numBytes(257) == 33 );
}
// ---------------------------------------------------------------
#if 0
#warning VERY LONG TIME TEST
TEST_CASE("genRegID", "[modbus][genRegID]" )
......
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