Commit 970c501c authored by Pavel Vainerman's avatar Pavel Vainerman

(Modbus): Начал работу над реализацией функции 0x2B(43).

Заложил и предварительно отладил структуры сообщений.
parent c77fe9f3
...@@ -29,7 +29,6 @@ static void print_help() ...@@ -29,7 +29,6 @@ static void print_help()
printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n"); printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n");
printf("[-x|--ignore-addr] - Ignore modbus RTU-address.\n"); printf("[-x|--ignore-addr] - Ignore modbus RTU-address.\n");
printf("[-p|--port] port - Server port. Default: 502.\n"); printf("[-p|--port] port - Server port. Default: 502.\n");
printf("[-v|--verbose] - Print all messages to stdout\n");
printf("[-c|--const-reply] val - Reply 'val' for all queries\n"); printf("[-c|--const-reply] val - Reply 'val' for all queries\n");
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
......
...@@ -14,6 +14,8 @@ static struct option longopts[] = { ...@@ -14,6 +14,8 @@ static struct option longopts[] = {
{ "read02", required_argument, 0, 'b' }, { "read02", required_argument, 0, 'b' },
{ "read03", required_argument, 0, 'r' }, { "read03", required_argument, 0, 'r' },
{ "read04", required_argument, 0, 'x' }, { "read04", required_argument, 0, 'x' },
// { "read43-13", required_argument, 0, 'u' },
{ "read43-14", required_argument, 0, 'e' },
{ "write05", required_argument, 0, 'f' }, { "write05", required_argument, 0, 'f' },
{ "write06", required_argument, 0, 'z' }, { "write06", required_argument, 0, 'z' },
{ "write0F", required_argument, 0, 'm' }, { "write0F", required_argument, 0, 'm' },
...@@ -40,14 +42,16 @@ static void print_help() ...@@ -40,14 +42,16 @@ static void print_help()
printf("[--read02] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n"); printf("[--read02] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n");
printf("[--read03] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n"); printf("[--read03] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n");
printf("[--read04] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n"); printf("[--read04] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n");
printf("[--diag08] slaveaddr subfunc [dat] - diagnostics request\n"); printf("[--diag08] slaveaddr subfunc [dat] - diagnostics request\n");
printf("[--read43-14] slaveaddr devID objID - (0x2B/0x0E): read device identification (devID=[1...4], objID=[0..255])\n");
// printf("[--read43-13] slaveaddr ... - (0x2B/0x0D): CANopen General Reference Request and Response PDU \n");
printf("[-i|--iaddr] ip - Modbus server ip. Default: 127.0.0.1\n"); printf("[-i|--iaddr] ip - Modbus server ip. Default: 127.0.0.1\n");
printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n"); printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n");
printf("[-p|--port] port - Modbus server port. Default: 502.\n"); printf("[-p|--port] port - Modbus server port. Default: 502.\n");
printf("[-t|--timeout] msec - Timeout. Default: 2000.\n"); printf("[-t|--timeout] msec - Timeout. Default: 2000.\n");
printf("[-o|--persistent-connection] - Use persistent-connection.\n"); printf("[-o|--persistent-connection] - Use persistent-connection.\n");
printf("[-l|--num-cycles] num - Number of cycles of exchange. Default: -1 - infinitely.\n"); printf("[-l|--num-cycles] num - Number of cycles of exchange. Default: -1 - infinitely.\n");
printf("[-v|--verbose] - Print all messages to stdout\n"); printf("[-v|--verbose] - Print all messages to stdout\n");
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
enum Command enum Command
...@@ -57,6 +61,8 @@ enum Command ...@@ -57,6 +61,8 @@ enum Command
cmdRead02, cmdRead02,
cmdRead03, cmdRead03,
cmdRead04, cmdRead04,
cmdRead43_13,
cmdRead43_14,
cmdWrite05, cmdWrite05,
cmdWrite06, cmdWrite06,
cmdWrite0F, cmdWrite0F,
...@@ -86,10 +92,12 @@ int main( int argc, char **argv ) ...@@ -86,10 +92,12 @@ int main( int argc, char **argv )
int tout = 2000; int tout = 2000;
DebugStream dlog; DebugStream dlog;
int ncycles = -1; int ncycles = -1;
ModbusRTU::ModbusByte devID = 0;
ModbusRTU::ModbusByte objID = 0;
try try
{ {
while( (opt = getopt_long(argc, argv, "hva:w:z:r:x:c:b:d:s:t:p:i:ol:d:",longopts,&optindex)) != -1 ) while( (opt = getopt_long(argc, argv, "hva:w:z:r:x:c:b:d:s:t:p:i:ol:d:e:u:",longopts,&optindex)) != -1 )
{ {
switch (opt) switch (opt)
{ {
...@@ -107,7 +115,7 @@ int main( int argc, char **argv ) ...@@ -107,7 +115,7 @@ int main( int argc, char **argv )
if( cmd == cmdNOP ) if( cmd == cmdNOP )
cmd = cmdRead03; cmd = cmdRead03;
case 'x': case 'x':
{
if( cmd == cmdNOP ) if( cmd == cmdNOP )
cmd = cmdRead04; cmd = cmdRead04;
slaveaddr = ModbusRTU::str2mbAddr( optarg ); slaveaddr = ModbusRTU::str2mbAddr( optarg );
...@@ -122,6 +130,28 @@ int main( int argc, char **argv ) ...@@ -122,6 +130,28 @@ int main( int argc, char **argv )
if( checkArg(optind+1,argc,argv) ) if( checkArg(optind+1,argc,argv) )
count = uni_atoi(argv[optind+1]); count = uni_atoi(argv[optind+1]);
}
break;
case 'e':
{
if( cmd == cmdNOP )
cmd = cmdRead43_14;
slaveaddr = ModbusRTU::str2mbAddr( optarg );
if( optind > argc )
{
cerr << "read command error: bad or no arguments..." << endl;
return 1;
}
if( checkArg(optind,argc,argv) )
devID = ModbusRTU::str2mbData(argv[optind]);
if( checkArg(optind+1,argc,argv) )
objID = uni_atoi(argv[optind+1]);
}
break; break;
case 'f': case 'f':
...@@ -354,6 +384,62 @@ int main( int argc, char **argv ) ...@@ -354,6 +384,62 @@ int main( int argc, char **argv )
} }
break; break;
case cmdRead43_14:
{
if( verb )
{
cout << "read43_14: slaveaddr=" << ModbusRTU::addr2str(slaveaddr)
<< " devID=" << ModbusRTU::dat2str(devID)
<< " objID=" << ModbusRTU::dat2str(objID)
<< endl;
}
ModbusRTU::MEIMessageRDI m(slaveaddr,devID,objID);
cout << " request: " << m << endl;
ModbusRTU::ModbusMessage tm( m.transport_msg() );
ModbusRTU::MEIMessageRDI m2(tm);
cout << " request2: " << m2 << endl;
ModbusRTU::MEIMessageRetRDI r(m2.addr,m2.devID,0x01,0x0FF,m2.objID);
r.addData(1,"Object 1");
r.addData(2,"Object 2");
r.addData(3,"Object 3");
cout << " response: " << r << endl;
ModbusRTU::ModbusMessage tm2( r.transport_msg() );
// cout << tm2 << endl;
/*
ModbusRTU::RDIObjectList dlist;
dlist.clear();
ModbusRTU::RDIObjectInfo rdi(1,"Obj1");
dlist.push_back(rdi);
for( ModbusRTU::RDIObjectList::iterator it=dlist.begin(); it!=dlist.end(); it++ )
cout << (int)it->id << " : " << it->val << endl;
*/
ModbusRTU::MEIMessageRetRDI r2(tm2);
cout << "response2: " << r2 << endl;
/*
ModbusRTU::ReadInputRetMessage ret = mb.read04(slaveaddr,reg,count);
if( verb )
cout << "(reply): " << ret << endl;
cout << "(reply): count=" << ModbusRTU::dat2str(ret.count) << endl;
for( int i=0; i<ret.count; i++ )
{
cout << i <<": (" << ModbusRTU::dat2str( reg + i ) << ") = " << (int)(ret.data[i])
<< " ("
<< ModbusRTU::dat2str(ret.data[i])
<< ")"
<< endl;
}
*/
}
break;
case cmdWrite05: case cmdWrite05:
{ {
if( verb ) if( verb )
......
...@@ -800,9 +800,12 @@ void MBSlave::initIterators() ...@@ -800,9 +800,12 @@ void MBSlave::initIterators()
void MBSlave::help_print( int argc, const char* const* argv ) void MBSlave::help_print( int argc, const char* const* argv )
{ {
cout << "Default: prefix='mbs'" << endl; cout << "Default: prefix='mbs'" << endl;
cout << "--prefix-reg-from-id 0,1 - Использовать в качестве регистра sensor ID" << endl;
cout << "--prefix-filter-field name - Считывать список опрашиваемых датчиков, только у которых есть поле field" << endl;
cout << "--prefix-filter-value val - Считывать список опрашиваемых датчиков, только у которых field=value" << endl;
cout << "--prefix-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl; cout << "--prefix-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-дачиком." << endl;
cout << "--prefix-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl; cout << "--prefix-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10." << endl;
cout << "--prefix-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl; cout << "--prefix-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')" << endl;
cout << "--prefix-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl; cout << "--prefix-initPause - Задержка перед инициализацией (время на активизация процесса)" << endl;
cout << "--prefix-respond-id - respond sensor id" << endl; cout << "--prefix-respond-id - respond sensor id" << endl;
cout << "--prefix-respond-invert [0|1] - invert respond logic" << endl; cout << "--prefix-respond-invert [0|1] - invert respond logic" << endl;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
#include <ostream> #include <ostream>
#include <bitset> #include <bitset>
#include <string>
#include <list>
#include "ModbusRTUErrors.h" #include "ModbusRTUErrors.h"
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
/* Основные предположения: /* Основные предположения:
...@@ -42,6 +44,7 @@ namespace ModbusRTU ...@@ -42,6 +44,7 @@ namespace ModbusRTU
fnWriteOutputRegisters = 0x10, /*!< write register outputs or memories */ fnWriteOutputRegisters = 0x10, /*!< write register outputs or memories */
fnReadFileRecord = 0x14, /*!< read file record */ fnReadFileRecord = 0x14, /*!< read file record */
fnWriteFileRecord = 0x15, /*!< write file record */ fnWriteFileRecord = 0x15, /*!< write file record */
fnMEI = 0x2B, /*!< Modbus Encapsulated Interface */
fnSetDateTime = 0x50, /*!< set date and time */ fnSetDateTime = 0x50, /*!< set date and time */
fnRemoteService = 0x53, /*!< call remote service */ fnRemoteService = 0x53, /*!< call remote service */
fnJournalCommand = 0x65, /*!< read,write,delete alarm journal */ fnJournalCommand = 0x65, /*!< read,write,delete alarm journal */
...@@ -70,11 +73,26 @@ namespace ModbusRTU ...@@ -70,11 +73,26 @@ namespace ModbusRTU
dgClearOverrunCounter = 0x14 /*!< (20) Clear Overrun Counter and FlagN.A. */ dgClearOverrunCounter = 0x14 /*!< (20) Clear Overrun Counter and FlagN.A. */
// 21 ...65535 RESERVED // 21 ...65535 RESERVED
}; };
// определение размера данных в зависимости от типа сообщения // определение размера данных в зависимости от типа сообщения
// возвращает -1 - если динамический размер сообщения или размер неизвестен // возвращает -1 - если динамический размер сообщения или размер неизвестен
int szRequestDiagnosticData( DiagnosticsSubFunction f ); int szRequestDiagnosticData( DiagnosticsSubFunction f );
/*! Read Device Identification ObjectID (0x2B/0xE) */
enum RDIObjectID
{
rdiVendorName = 0x0,
rdiProductCode = 0x1,
rdiMajorMinorRevision = 0x2,
rdiVendorURL = 0x3,
rdiProductName = 0x4,
rdiModelName = 0x5,
rdiUserApplicationName = 0x6
// 0x07 .. 0x7F - reserved
// 0x80 .. 0xFF - optionaly defined (product dependant)
};
// -----------------------------------------------------------------------
/*! различные базовые константы */ /*! различные базовые константы */
enum enum
{ {
...@@ -1011,6 +1029,110 @@ namespace ModbusRTU ...@@ -1011,6 +1029,110 @@ namespace ModbusRTU
std::ostream& operator<<(std::ostream& os, DiagnosticRetMessage& m ); std::ostream& operator<<(std::ostream& os, DiagnosticRetMessage& m );
std::ostream& operator<<(std::ostream& os, DiagnosticRetMessage* m ); std::ostream& operator<<(std::ostream& os, DiagnosticRetMessage* m );
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
/*! Modbus Encapsulated Interface (0x2B). Read Device Identification (0x0E) */
struct MEIMessageRDI:
public ModbusHeader
{
ModbusByte type; /*!< for RDI must be 0x0E */
ModbusByte devID; /*!< Read Device ID code */
ModbusByte objID; /*!< Object Id */
ModbusCRC crc; /*!< контрольная сумма */
// ------- to slave -------
MEIMessageRDI( ModbusAddr addr, ModbusByte devID, ModbusByte objID );
/*! преобразование для посылки в сеть */
ModbusMessage transport_msg();
// ------- from master -------
MEIMessageRDI( ModbusMessage& m );
MEIMessageRDI& operator=( ModbusMessage& m );
void init( ModbusMessage& m );
/*! размер данных(после заголовка) у данного типа сообщения */
static inline int szData(){ return sizeof(ModbusByte)*3 + szCRC; }
// вспомогательные функции
bool checkFormat();
}__attribute__((packed));
// -----------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, MEIMessageRDI& m );
std::ostream& operator<<(std::ostream& os, MEIMessageRDI* m );
// -----------------------------------------------------------------------
struct RDIObjectInfo
{
RDIObjectInfo():id(0),val(""){}
RDIObjectInfo( ModbusByte id, const std::string v ):id(id),val(v){}
RDIObjectInfo( ModbusByte id, ModbusByte* dat, ModbusByte len );
ModbusByte id;
std::string val;
};
typedef std::list<RDIObjectInfo> RDIObjectList;
/*! Ответ для 0x2B/0x0E */
struct MEIMessageRetRDI:
public ModbusHeader
{
ModbusByte type; /*!< 0x0E */
ModbusByte devID; /*!< Read Device ID code */
ModbusByte conformity; /*!< Conformity level (0x01 or 0x02 or 0x03 or 0x81 or 0x82 or 0x83) */
ModbusByte mf; /*!< More Follows (00/FF) */
ModbusByte objID; /*!< Object ID number */
ModbusByte objNum; /*!< Number of objects */
RDIObjectList dlist;
ModbusCRC crc;
// ------- from slave -------
MEIMessageRetRDI( ModbusMessage& m );
MEIMessageRetRDI& operator=( ModbusMessage& m );
void init( ModbusMessage& m );
/*! размер предварительного заголовка (после основного до фактических данных) */
static inline int szHead()
{
return sizeof(ModbusByte)*6;
}
/*! узнать длину данных следующий за предварительным заголовком ( в байтах ) */
static int getDataLen( ModbusMessage& m );
// ------- to master -------
MEIMessageRetRDI( ModbusAddr _from, ModbusByte devID, ModbusByte conformity, ModbusByte mf, ModbusByte objID );
/*! добавление данных.
* \return TRUE - если удалось
* \return FALSE - если НЕ удалось
*/
bool addData( ModbusByte id, const std::string value );
bool addData( RDIObjectInfo& dat );
/*! очистка данных */
void clear();
/*! проверка на переполнение */
inline bool isFull()
{
return ( bcnt >= MAXLENPACKET );
}
/*! размер данных(после заголовка) у данного типа сообщения */
int szData();
/*! преобразование для посылки в сеть */
ModbusMessage transport_msg();
int bcnt; /*! размер данных в байтах, внутреннее служебное поле */
};
std::ostream& operator<<(std::ostream& os, MEIMessageRetRDI& m );
std::ostream& operator<<(std::ostream& os, MEIMessageRetRDI* m );
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
/*! Чтение информации об ошибке */ /*! Чтение информации об ошибке */
struct JournalCommandMessage: struct JournalCommandMessage:
......
...@@ -2328,6 +2328,274 @@ std::ostream& ModbusRTU::operator<<(std::ostream& os, DiagnosticRetMessage* m ) ...@@ -2328,6 +2328,274 @@ std::ostream& ModbusRTU::operator<<(std::ostream& os, DiagnosticRetMessage* m )
return os << (*m); return os << (*m);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// -------------------------------------------------------------------------
MEIMessageRDI::MEIMessageRDI( ModbusAddr a, ModbusByte dev, ModbusByte oid ):
type(0x0E),
devID(dev),
objID(oid)
{
addr = a;
func = fnMEI;
}
// -------------------------------------------------------------------------
ModbusMessage MEIMessageRDI::transport_msg()
{
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader+szData() );
ModbusMessage mm;
// копируем заголовок
memcpy(&mm,this,szModbusHeader);
mm.data[0] = type;
mm.data[1] = devID;
mm.data[2] = objID;
int ind = 3;
// пересчитываем CRC по перевёрнутым данным
ModbusData crc = checkCRC( (ModbusByte*)(&mm), szModbusHeader+ind );
// копируем CRC (последний элемент). Без переворачивания...
memcpy(&(mm.data[ind]),&crc,szCRC);
ind+=szCRC;
// длина сообщения...
mm.len = ind;
return mm;
}
// -------------------------------------------------------------------------
MEIMessageRDI::MEIMessageRDI( ModbusMessage& m )
{
init(m);
}
MEIMessageRDI& MEIMessageRDI::operator=( ModbusMessage& m )
{
init(m);
return *this;
}
// -------------------------------------------------------------------------
void MEIMessageRDI::init( ModbusMessage& m )
{
assert( m.func == fnMEI );
memset(this,0,sizeof(*this));
// copy not include CRC
memcpy(this,&m,szModbusHeader+m.len);
// потом проверяем
if( !checkFormat() )
{
#ifdef DEBUG
cerr << "(MEIMessageRDI): BAD format!" << endl;
cerr << "MEI type != 0x0E (read '" << type << "')"
<< endl;
#endif
}
// последний элемент это CRC
memcpy(&crc,&(m.data[m.len-szCRC]),szCRC);
}
// -------------------------------------------------------------------------
bool MEIMessageRDI::checkFormat()
{
return ( type == 0x0E );
}
// -------------------------------------------------------------------------
std::ostream& ModbusRTU::operator<<(std::ostream& os, MEIMessageRDI& m )
{
os << "addr=" << addr2str(m.addr)
<< " func=0x" << b2str(m.func)
<< " type=0x" << b2str(m.type)
<< " devID=0x" << b2str(m.devID)
<< " objID=0x" << b2str(m.objID);
return os;
}
std::ostream& ModbusRTU::operator<<(std::ostream& os, MEIMessageRDI* m )
{
return os << (*m);
}
// -------------------------------------------------------------------------
MEIMessageRetRDI::MEIMessageRetRDI( ModbusMessage& m ):
type(0),
devID(0),
conformity(0),
mf(0),
objID(0),
objNum(0),
bcnt(0)
{
init(m);
}
// -------------------------------------------------------------------------
MEIMessageRetRDI& MEIMessageRetRDI::operator=( ModbusMessage& m )
{
init(m);
return *this;
}
// -------------------------------------------------------------------------
RDIObjectInfo::RDIObjectInfo( ModbusByte id, ModbusByte* dat, ModbusByte len ):
id(id),
val("")
{
val.reserve(len);
for( int i=0; i<len; i++ )
val.push_back( (char)dat[i] );
}
// -------------------------------------------------------------------------
void MEIMessageRetRDI::init( ModbusMessage& m )
{
assert( m.func == fnMEI );
addr = m.addr;
func = m.func;
type = m.data[0];
if( type != 0x0E )
throw mbException(erInvalidFormat);
if( m.len < 6 )
throw mbException(erInvalidFormat);
devID = m.data[1];
conformity = m.data[2];
mf = m.data[3];
objID = m.data[4];
objNum = m.data[5];
bcnt = 0;
dlist.clear();
int i = 6;
if( objNum > 0 )
{
if( m.len < 7 )
throw mbException(erInvalidFormat);
while( i < m.len && dlist.size() < objNum )
{
ModbusByte id = m.data[i];
int dlen = (int)(m.data[i+1]);
if( m.len < (i+1+dlen+szCRC) )
throw mbException(erInvalidFormat);
RDIObjectInfo rdi(id, &(m.data[i+2]), dlen );
dlist.push_back(rdi);
bcnt+=dlen+2;
i += (dlen+2);
}
}
memcpy(&crc,&(m.data[i]),szCRC);
}
// -------------------------------------------------------------------------
MEIMessageRetRDI::MEIMessageRetRDI( ModbusAddr _addr, ModbusByte devID, ModbusByte conformity, ModbusByte mf, ModbusByte objID ):
type(0x0E),
devID(devID),
conformity(conformity),
mf(mf),
objID(objID),
objNum(0),
bcnt(0)
{
addr = _addr;
func = fnMEI;
}
// -------------------------------------------------------------------------
bool MEIMessageRetRDI::addData( ModbusByte id, const std::string val )
{
if( isFull() )
return false;
RDIObjectInfo r(id,val);
dlist.push_back(r);
objNum = dlist.size();
bcnt += val.size() + 2; // 2 = 'id'(byte) + 'len'(byte)
return true;
}
// -------------------------------------------------------------------------
void MEIMessageRetRDI::clear()
{
dlist.clear();
bcnt = 0;
}
// -------------------------------------------------------------------------
ModbusMessage MEIMessageRetRDI::transport_msg()
{
ModbusMessage mm;
assert( sizeof(ModbusMessage) >= (unsigned int)szModbusHeader+szData() );
// копируем заголовок и данные
memcpy(&mm,this,szModbusHeader);
mm.data[0] = type;
mm.data[1] = devID;
mm.data[2] = conformity;
mm.data[3] = mf;
mm.data[4] = objID;
mm.data[5] = objNum;
int ind = 6;
for( RDIObjectList::iterator it = dlist.begin(); it!=dlist.end() && ind <= MAXLENPACKET; ++it )
{
mm.data[ind++] = it->id;
int dlen = it->val.size(); // !! не копируем завершающий символ
mm.data[ind++] = dlen;
memcpy(&(mm.data[ind]), it->val.data(), dlen );
ind += dlen;
}
// пересчитываем CRC по перевёрнутым данным
ModbusData crc = checkCRC( (ModbusByte*)(&mm), szModbusHeader+ind );
// копируем CRC (последний элемент). Без переворачивания...
memcpy(&(mm.data[ind]),&crc,szCRC);
ind+=szCRC;
// длина сообщения...
mm.len = ind;
return mm;
}
// -------------------------------------------------------------------------
int MEIMessageRetRDI::szData()
{
// заголовочные поля + фактическое число данных + контрольная сумма
return 6 + bcnt + szCRC;
}
// -------------------------------------------------------------------------
std::ostream& ModbusRTU::operator<<(std::ostream& os, MEIMessageRetRDI& m )
{
// return mbPrintMessage(os,(ModbusByte*)(&m), szModbusHeader + m.szData() );
os << "addr=" << addr2str(m.addr)
<< " func=0x" << b2str(m.func)
<< " type=0x" << b2str(m.type)
<< " devID=0x" << b2str(m.devID)
<< " conformity=0x" << b2str(m.conformity)
<< " mf=0x" << b2str(m.mf)
<< " objID=0x" << b2str(m.objID)
<< " objNum=" << (int)(m.objNum);
if( !m.dlist.empty() )
{
os << endl;
for( RDIObjectList::iterator it=m.dlist.begin(); it!=m.dlist.end(); it++ )
os << " " << (int)(it->id) << " : " << it->val << endl;
}
return os;
}
std::ostream& ModbusRTU::operator<<(std::ostream& os, MEIMessageRetRDI* m )
{
return os << (*m);
}
// -------------------------------------------------------------------------
JournalCommandMessage::JournalCommandMessage( ModbusMessage& m ) JournalCommandMessage::JournalCommandMessage( ModbusMessage& m )
{ {
assert( m.func == fnJournalCommand ); assert( m.func == fnJournalCommand );
...@@ -2390,7 +2658,7 @@ bool JournalCommandRetMessage::setData( ModbusByte* buf, int len ) ...@@ -2390,7 +2658,7 @@ bool JournalCommandRetMessage::setData( ModbusByte* buf, int len )
if( len%sizeof(ModbusData) ) if( len%sizeof(ModbusData) )
count++; count++;
bcnt = count*sizeof(ModbusData); bcnt = count*sizeof(ModbusData);
return true; return true;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
......
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