Commit 37afca41 authored by Pavel Vainerman's avatar Pavel Vainerman

(Modbus): сделана предварительная реализация запроса и ответа на

функцию 43/14 (0x2B/0x0E)
parent 970c501c
......@@ -3,8 +3,9 @@
//#include <string.h>
//#include <errno.h>
#include <sstream>
#include <UniSetTypes.h>
#include "UniSetTypes.h"
#include "MBSlave.h"
#include "config.h"
// -------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
......@@ -48,6 +49,7 @@ MBSlave::MBSlave( ModbusRTU::ModbusAddr addr, const std::string dev, const std::
rscomm->connectRemoteService( sigc::mem_fun(this, &MBSlave::remoteService) );
rscomm->connectFileTransfer( sigc::mem_fun(this, &MBSlave::fileTransfer) );
rscomm->connectDiagnostics( sigc::mem_fun(this, &MBSlave::diagnostics) );
rscomm->connectMEIRDI( sigc::mem_fun(this, &MBSlave::read4314) );
rscomm->setRecvTimeout(2000);
......@@ -467,4 +469,38 @@ ModbusRTU::mbErrCode MBSlave::diagnostics( ModbusRTU::DiagnosticMessage& query,
return ModbusRTU::erOperationFailed;
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply )
{
if( verbose )
cout << "(read4314): " << query << endl;
if( query.devID == rdiVendorName )
{
reply.mf = 0;
reply.conformity = 0;
reply.addData(rdiVendorName,"etersoft");
reply.addData(rdiProductCode, PACKAGE_NAME);
reply.addData(rdiMajorMinorRevision,PACKAGE_VERSION);
return erNoError;
}
else if( query.devID == rdiProductCode )
{
reply.mf = 0;
reply.conformity = 0;
reply.addData(rdiProductCode,PACKAGE_NAME);
return erNoError;
}
else if( query.devID == rdiMajorMinorRevision )
{
reply.mf = 0;
reply.conformity = 0;
reply.addData(rdiMajorMinorRevision,PACKAGE_VERSION);
return erNoError;
}
return ModbusRTU::erOperationFailed;
}
// -------------------------------------------------------------------------
......@@ -91,6 +91,9 @@ class MBSlave
ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
ModbusRTU::DiagnosticRetMessage& reply );
ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply );
/*! интерфейс ModbusRTUSlave для обмена по RS */
ModbusRTUSlaveSlot* rscomm;
ModbusRTU::ModbusAddr addr; /*!< адрес данного узла */
......
......@@ -5,6 +5,7 @@
#include <sstream>
#include <UniSetTypes.h>
#include "MBTCPServer.h"
#include "config.h"
// -------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
......@@ -42,6 +43,7 @@ MBTCPServer::MBTCPServer( ModbusAddr myaddr, const string inetaddr, int port, bo
sslot->connectWriteOutput( sigc::mem_fun(this, &MBTCPServer::writeOutputRegisters) );
sslot->connectWriteSingleOutput( sigc::mem_fun(this, &MBTCPServer::writeOutputSingleRegister) );
sslot->connectDiagnostics( sigc::mem_fun(this, &MBTCPServer::diagnostics) );
sslot->connectMEIRDI( sigc::mem_fun(this, &MBTCPServer::read4314) );
sslot->connectJournalCommand( sigc::mem_fun(this, &MBTCPServer::journalCommand) );
sslot->connectSetDateTime( sigc::mem_fun(this, &MBTCPServer::setDateTime) );
sslot->connectRemoteService( sigc::mem_fun(this, &MBTCPServer::remoteService) );
......@@ -459,4 +461,37 @@ ModbusRTU::mbErrCode MBTCPServer::diagnostics( ModbusRTU::DiagnosticMessage& que
return ModbusRTU::erOperationFailed;
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBTCPServer::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply )
{
if( verbose )
cout << "(read4314): " << query << endl;
if( query.devID == rdiVendorName )
{
reply.mf = 0;
reply.conformity = 0;
reply.addData(rdiVendorName,"etersoft");
reply.addData(rdiProductCode, PACKAGE_NAME);
reply.addData(rdiMajorMinorRevision,PACKAGE_VERSION);
return erNoError;
}
else if( query.devID == rdiProductCode )
{
reply.mf = 0;
reply.conformity = 0;
reply.addData(rdiProductCode,PACKAGE_NAME);
return erNoError;
}
else if( query.devID == rdiMajorMinorRevision )
{
reply.mf = 0;
reply.conformity = 0;
reply.addData(rdiMajorMinorRevision,PACKAGE_VERSION);
return erNoError;
}
return ModbusRTU::erOperationFailed;
}
// -------------------------------------------------------------------------
......@@ -72,6 +72,9 @@ class MBTCPServer
ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
ModbusRTU::DiagnosticRetMessage& reply );
ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply );
/*! обработка запросов на чтение ошибок */
ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query,
ModbusRTU::JournalCommandRetMessage& reply );
......
......@@ -14,8 +14,8 @@ static struct option longopts[] = {
{ "read02", required_argument, 0, 'b' },
{ "read03", required_argument, 0, 'r' },
{ "read04", required_argument, 0, 'x' },
// { "read43-13", required_argument, 0, 'u' },
{ "read43-14", required_argument, 0, 'e' },
// { "read4313", required_argument, 0, 'u' },
{ "read4314", required_argument, 0, 'e' },
{ "write05", required_argument, 0, 'f' },
{ "write06", required_argument, 0, 'z' },
{ "write0F", required_argument, 0, 'm' },
......@@ -43,7 +43,7 @@ static void print_help()
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("[--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("[--read4314] 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("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n");
......@@ -388,55 +388,17 @@ int main( int argc, char **argv )
{
if( verb )
{
cout << "read43_14: slaveaddr=" << ModbusRTU::addr2str(slaveaddr)
cout << "read4314: 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);
ModbusRTU::MEIMessageRetRDI ret = mb.read4314(slaveaddr,devID,objID);
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;
}
*/
else
cout << "(reply): objNum=" << (int)ret.objNum << endl << ret.dlist << endl;
}
break;
......
......@@ -147,7 +147,7 @@ fi
AC_SUBST(UNISET_CODEGEN)
echo "UNISET_CODEGEN: $UNISET_CODEGEN"
UNISET_CFLAGS="-I \$(top_builddir)/include"
UNISET_CFLAGS="-I \$(top_builddir) -I \$(top_builddir)/include"
AC_SUBST(UNISET_CFLAGS)
UNISET_LIBS="\$(top_builddir)/lib/libUniSet.la"
AC_SUBST(UNISET_LIBS)
......
......@@ -88,6 +88,14 @@ class ModbusClient
ModbusRTU::ModbusData dat=0 )
throw(ModbusRTU::mbException);
/*! Modbus Encapsulated Interface 43(0x2B)
Read Device Identification 14(0x0E)
*/
ModbusRTU::MEIMessageRetRDI read4314( ModbusRTU::ModbusAddr addr,
ModbusRTU::ModbusByte devID,
ModbusRTU::ModbusByte objID )
throw(ModbusRTU::mbException);
/*! Установить системное время (0x50)
hour - часы [0..23]
min - минуты [0..59]
......
......@@ -54,6 +54,9 @@ class ModbusRTUSlaveSlot:
virtual ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
ModbusRTU::DiagnosticRetMessage& reply );
virtual ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply );
virtual ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query,
ModbusRTU::JournalCommandRetMessage& reply );
......
......@@ -150,7 +150,15 @@ class ModbusServer
virtual ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
ModbusRTU::DiagnosticRetMessage& reply )=0;
/*! Обработка запроса 43(0x2B).
\param query - запрос
\param reply - ответ. Заполняется в обработчике.
\return Результат обработки
*/
virtual ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply )=0;
/*! Обработка запроса по журналу (0x65)
\param query - запрос
\param reply - ответ. Заполняется в обработчике.
......
......@@ -48,6 +48,10 @@ class ModbusServerSlot
typedef sigc::slot<ModbusRTU::mbErrCode,
ModbusRTU::DiagnosticMessage&,
ModbusRTU::DiagnosticRetMessage&> DiagnosticsSlot;
typedef sigc::slot<ModbusRTU::mbErrCode,
ModbusRTU::MEIMessageRDI&,
ModbusRTU::MEIMessageRetRDI&> MEIRDISlot;
typedef sigc::slot<ModbusRTU::mbErrCode,
ModbusRTU::JournalCommandMessage&,
......@@ -86,6 +90,9 @@ class ModbusServerSlot
/*! подключение обработчика 'записи данных' 0x08 */
void connectDiagnostics( DiagnosticsSlot sl );
/*! подключение обработчика 0x2B(43) */
void connectMEIRDI( MEIRDISlot sl );
/*! подключение обработчика 'записи данных' 0x0F */
void connectForceCoils( ForceCoilsSlot sl );
......@@ -116,6 +123,7 @@ class ModbusServerSlot
ForceSingleCoilSlot slForceSingleCoil;
WriteSingleOutputSlot slWriteSingleOutputs;
DiagnosticsSlot slDiagnostics;
MEIRDISlot slMEIRDI;
JournalCommandSlot slJournalCommand;
SetDateTimeSlot slSetDateTime;
RemoteServiceSlot slRemoteService;
......
......@@ -47,6 +47,9 @@ class ModbusTCPServerSlot:
virtual ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
ModbusRTU::DiagnosticRetMessage& reply );
virtual ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply );
virtual ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query,
ModbusRTU::JournalCommandRetMessage& reply );
......
......@@ -1049,6 +1049,11 @@ namespace ModbusRTU
MEIMessageRDI& operator=( ModbusMessage& m );
void init( ModbusMessage& m );
/*! размер предварительного заголовка
* (после основного до фактических данных)
*/
static inline int szHead(){ return sizeof(ModbusByte)*3; }
/*! размер данных(после заголовка) у данного типа сообщения */
static inline int szData(){ return sizeof(ModbusByte)*3 + szCRC; }
......@@ -1088,18 +1093,22 @@ namespace ModbusRTU
ModbusCRC crc;
// ------- from slave -------
MEIMessageRetRDI();
MEIMessageRetRDI( ModbusMessage& m );
MEIMessageRetRDI& operator=( ModbusMessage& m );
void init( ModbusMessage& m );
// предварительная инициализации, только заголовочной части, без данных
void pre_init( ModbusMessage& m );
/*! размер предварительного заголовка (после основного до фактических данных) */
static inline int szHead()
{
return sizeof(ModbusByte)*6;
}
/*! узнать длину данных следующий за предварительным заголовком ( в байтах ) */
static int getDataLen( ModbusMessage& m );
// /*! узнать длину данных следующих за предварительным заголовком ( в байтах ) */
// static int getDataLen( ModbusMessage& m );
// ------- to master -------
MEIMessageRetRDI( ModbusAddr _from, ModbusByte devID, ModbusByte conformity, ModbusByte mf, ModbusByte objID );
......@@ -1131,6 +1140,8 @@ namespace ModbusRTU
std::ostream& operator<<(std::ostream& os, MEIMessageRetRDI& m );
std::ostream& operator<<(std::ostream& os, MEIMessageRetRDI* m );
std::ostream& operator<<(std::ostream& os, RDIObjectList& dl );
std::ostream& operator<<(std::ostream& os, RDIObjectList* dl );
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
......
......@@ -163,6 +163,21 @@ DiagnosticRetMessage ModbusClient::diag08( ModbusAddr addr,
throw mbException(res);
}
// --------------------------------------------------------------------------------
ModbusRTU::MEIMessageRetRDI ModbusClient::read4314( ModbusRTU::ModbusAddr addr,
ModbusRTU::ModbusByte devID,
ModbusRTU::ModbusByte objID )
throw(ModbusRTU::mbException)
{
MEIMessageRDI msg(addr,devID,objID);
qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr,qbuf,reply,replyTimeOut_ms);
if( res==erNoError )
return MEIMessageRetRDI(reply);
throw mbException(res);
}
// --------------------------------------------------------------------------------
SetDateTimeRetMessage ModbusClient::setDateTime( ModbusAddr addr, ModbusByte hour, ModbusByte min, ModbusByte sec,
ModbusByte day, ModbusByte mon, ModbusByte year,
ModbusByte century )
......@@ -464,6 +479,10 @@ mbErrCode ModbusClient::recv_pdu( ModbusByte qfunc, ModbusMessage& rbuf, timeout
rbuf.len = DiagnosticRetMessage::szHead();
break;
case fnMEI:
rbuf.len = MEIMessageRetRDI::szHead();
break;
case fnSetDateTime:
rbuf.len = SetDateTimeRetMessage::szData();
if( crcNoCheckit )
......@@ -890,6 +909,115 @@ mbErrCode ModbusClient::recv_pdu( ModbusByte qfunc, ModbusMessage& rbuf, timeout
return erNoError;
}
else if( rbuf.func == fnMEI )
{
MEIMessageRetRDI mPreRDI;
mPreRDI.pre_init(rbuf);
if( mPreRDI.objNum > 0 )
{
int onum = 0;
while( rlen < sizeof(rbuf) && onum < mPreRDI.objNum )
{
// сперва получаем два байта, для определения длины последующих данных
int szDataLen = 2; // object id + len
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])),szDataLen);
if( rlen1 < szDataLen )
{
rbuf.len = bcnt + rlen1 - szModbusHeader;
if( dlog.debugging(Debug::WARN) )
{
dlog[Debug::WARN] << "(0x2B/0x0E): buf: " << rbuf << endl;
dlog[Debug::WARN] << "(0x2B/0x0E)("
<< (int)rbuf.func << "):(fnMEI) "
<< "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl;
}
cleanupChannel();
return erInvalidFormat;
}
rlen += szDataLen;
bcnt += szDataLen;
// теперь получаем собственно данные
szDataLen = rbuf.data[rlen-1]; // последний (предыдущий) байт - это длина данных
rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])),szDataLen);
if( rlen1 < szDataLen )
{
rbuf.len = bcnt + rlen1 - szModbusHeader;
if( dlog.debugging(Debug::WARN) )
{
dlog[Debug::WARN] << "(0x2B/0x0E): buf: " << rbuf << endl;
dlog[Debug::WARN] << "(0x2B/0x0E)("
<< (int)rbuf.func << "):(fnMEI) "
<< "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl;
}
cleanupChannel();
return erInvalidFormat;
}
rlen += szDataLen;
bcnt += szDataLen;
onum++;
}
}
rbuf.len = bcnt - szModbusHeader;
if( crcNoCheckit )
{
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(recv)(fnMEI): recv buf: " << rbuf << endl;
return erNoError;
}
// теперь получаем CRC
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])),szCRC);
if( rlen1 < szCRC )
{
rbuf.len = bcnt + rlen1 - szModbusHeader;
if( dlog.debugging(Debug::WARN) )
{
dlog[Debug::WARN] << "(0x2B/0x0E): buf: " << rbuf << endl;
dlog[Debug::WARN] << "(0x2B/0x0E)("
<< (int)rbuf.func << "):(fnMEI) "
<< "(CRC): Получили данных меньше чем ждали...("
<< rlen1 << " < " << szCRC << ")" << endl;
}
cleanupChannel();
return erInvalidFormat;
}
bcnt += rlen1;
rbuf.len = bcnt - szModbusHeader;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(recv)(fnMEI): recv buf: " << rbuf << endl;
MEIMessageRetRDI mRDI(rbuf);
// Проверяем контрольную сумму
// от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = checkCRC((ModbusByte*)(&rbuf),bcnt-szCRC);
if( tcrc != mRDI.crc )
{
ostringstream err;
err << "(recv:fnMEI): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRDI.crc);
if( dlog.debugging(Debug::WARN) )
dlog[Debug::WARN] << err.str() << endl;
return erBadCheckSum;
}
return erNoError;
}
else if( rbuf.func == fnSetDateTime )
{
SetDateTimeRetMessage mSet(rbuf);
......
......@@ -90,6 +90,15 @@ mbErrCode ModbusRTUSlaveSlot::diagnostics( DiagnosticMessage& query,
return slDiagnostics(query,reply);
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusRTUSlaveSlot::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply )
{
if( !slMEIRDI )
return erOperationFailed;
return slMEIRDI(query,reply);
}
// -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::forceSingleCoil( ForceSingleCoilMessage& query,
ForceSingleCoilRetMessage& reply )
{
......
......@@ -289,6 +289,37 @@ mbErrCode ModbusServer::processing( ModbusMessage& buf )
// --------------------------------
return res;
}
else if( buf.func == fnMEI )
{
MEIMessageRDI mRDI(buf);
MEIMessageRetRDI reply( buf.addr, mRDI.devID, 0, 0, mRDI.objID );
mbErrCode res = read4314( mRDI, reply );
// в случае ошибок ответа не посылаем
if( res != erNoError )
{
dlog[Debug::WARN] << "(0x2B/0x0E): reply: " << mbErr2Str(res) << endl;
// Если ошибка подразумевает посылку ответа с сообщением об ошибке
// то посылаем
if( res < erInternalErrorCode )
{
ErrorRetMessage em( mRDI.addr, mRDI.func, res );
buf = em.transport_msg();
return send(buf);
}
return res;
}
// отвечаем (используя тотже буфер, который будет очищен!!!)...
buf = reply.transport_msg();
// -----------------------------------
res = send(buf);
printProcessingTime();
// --------------------------------
return res;
}
else if( buf.func == fnForceSingleCoil )
{
ForceSingleCoilMessage mWrite(buf);
......@@ -623,7 +654,11 @@ mbErrCode ModbusServer::recv_pdu( ModbusMessage& rbuf, timeout_t timeout )
case fnDiagnostics:
rbuf.len = DiagnosticMessage::szHead();
break;
case fnMEI:
rbuf.len = MEIMessageRDI::szHead();
break;
case fnJournalCommand:
rbuf.len = JournalCommandMessage::szData();
if( crcNoCheckit )
......@@ -1109,6 +1144,58 @@ mbErrCode ModbusServer::recv_pdu( ModbusMessage& rbuf, timeout_t timeout )
}
*/
return erNoError;
}
else if( rbuf.func == fnMEI )
{
if( !crcNoCheckit )
{
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])),szCRC);
if( rlen1 < szCRC )
{
if( dlog.debugging(Debug::WARN) )
{
rbuf.len = bcnt + rlen1 - szModbusHeader;
dlog[Debug::WARN] << "(0x2B/0x0E): buf: " << rbuf << endl;
dlog[Debug::WARN] << "(0x2B/0x0E)("
<< rbuf.func << "):(fnMEI) "
<< "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szCRC << ")" << endl;
}
cleanupChannel();
return erInvalidFormat;
}
bcnt += rlen1;
rbuf.len = bcnt - szModbusHeader;
}
MEIMessageRDI mRDI(rbuf);
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(0x2B/0x0E): recv buf: " << rbuf << endl;
if( crcNoCheckit )
return erNoError;
// Проверяем контрольную сумму
// от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead() + mWrite.bcnt;
ModbusData tcrc = checkCRC((ModbusByte*)(&rbuf),bcnt-szCRC);
if( tcrc != mRDI.crc )
{
if( dlog.debugging(Debug::WARN) )
{
ostringstream err;
err << "(0x2B/0x0E): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRDI.crc);
dlog[Debug::WARN] << err.str() << endl;
}
cleanupChannel();
return erBadCheckSum;
}
return erNoError;
}
else if( rbuf.func == fnJournalCommand )
{
......
......@@ -55,6 +55,11 @@ void ModbusServerSlot::connectDiagnostics( DiagnosticsSlot sl )
slDiagnostics = sl;
}
// -------------------------------------------------------------------------
void ModbusServerSlot::connectMEIRDI( MEIRDISlot sl )
{
slMEIRDI = sl;
}
// -------------------------------------------------------------------------
void ModbusServerSlot::connectForceSingleCoil( ForceSingleCoilSlot sl )
{
slForceSingleCoil = sl;
......
......@@ -84,6 +84,15 @@ mbErrCode ModbusTCPServerSlot::diagnostics( DiagnosticMessage& query,
return slDiagnostics(query,reply);
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPServerSlot::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply )
{
if( !slMEIRDI )
return erOperationFailed;
return slMEIRDI(query,reply);
}
// -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::forceSingleCoil( ForceSingleCoilMessage& query,
ForceSingleCoilRetMessage& reply )
{
......
......@@ -2358,7 +2358,7 @@ ModbusMessage MEIMessageRDI::transport_msg()
ind+=szCRC;
// длина сообщения...
mm.len = ind;
mm.len = szData();
return mm;
}
// -------------------------------------------------------------------------
......@@ -2445,7 +2445,7 @@ RDIObjectInfo::RDIObjectInfo( ModbusByte id, ModbusByte* dat, ModbusByte len ):
val.push_back( (char)dat[i] );
}
// -------------------------------------------------------------------------
void MEIMessageRetRDI::init( ModbusMessage& m )
void MEIMessageRetRDI::pre_init( ModbusMessage& m )
{
assert( m.func == fnMEI );
......@@ -2465,10 +2465,30 @@ void MEIMessageRetRDI::init( ModbusMessage& m )
mf = m.data[3];
objID = m.data[4];
objNum = m.data[5];
}
// -------------------------------------------------------------------------
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 )
{
......@@ -2479,7 +2499,7 @@ void MEIMessageRetRDI::init( ModbusMessage& m )
{
ModbusByte id = m.data[i];
int dlen = (int)(m.data[i+1]);
if( m.len < (i+1+dlen+szCRC) )
if( m.len < (i+1+dlen) )
throw mbException(erInvalidFormat);
RDIObjectInfo rdi(id, &(m.data[i+2]), dlen );
......@@ -2493,6 +2513,19 @@ void MEIMessageRetRDI::init( ModbusMessage& m )
memcpy(&crc,&(m.data[i]),szCRC);
}
// -------------------------------------------------------------------------
MEIMessageRetRDI::MEIMessageRetRDI():
type(0x00),
devID(0),
conformity(0),
mf(0),
objID(0),
objNum(0),
bcnt(0)
{
addr = 0;
func = fnUnknown;
}
// -------------------------------------------------------------------------
MEIMessageRetRDI::MEIMessageRetRDI( ModbusAddr _addr, ModbusByte devID, ModbusByte conformity, ModbusByte mf, ModbusByte objID ):
type(0x0E),
devID(devID),
......@@ -2595,6 +2628,22 @@ std::ostream& ModbusRTU::operator<<(std::ostream& os, MEIMessageRetRDI* m )
return os << (*m);
}
// -------------------------------------------------------------------------
std::ostream& ModbusRTU::operator<<(std::ostream& os,RDIObjectList& dlist )
{
if( !dlist.empty() )
{
for( RDIObjectList::iterator it=dlist.begin(); it!=dlist.end(); it++ )
os << " " << (int)(it->id) << " : " << it->val << endl;
}
return os;
}
std::ostream& ModbusRTU::operator<<(std::ostream& os, RDIObjectList* l )
{
return os << (*l);
}
// -------------------------------------------------------------------------
JournalCommandMessage::JournalCommandMessage( ModbusMessage& m )
{
......
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