Commit 316d7772 authored by Pavel Vainerman's avatar Pavel Vainerman Committed by Pavel Vainerman

(modbus): make style

parent 08cccaf0
...@@ -24,1462 +24,1462 @@ ...@@ -24,1462 +24,1462 @@
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace uniset; using namespace uniset;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusClient::ModbusClient(): ModbusClient::ModbusClient():
replyTimeOut_ms(2000), replyTimeOut_ms(2000),
aftersend_msec(0), aftersend_msec(0),
sleepPause_usec(100), sleepPause_usec(100),
crcNoCheckit(false), crcNoCheckit(false),
sendMutex("ModbusClient_sendMutex") sendMutex("ModbusClient_sendMutex")
{ {
dlog = make_shared<DebugStream>(); dlog = make_shared<DebugStream>();
tmProcessing.setTiming(replyTimeOut_ms); tmProcessing.setTiming(replyTimeOut_ms);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusClient::~ModbusClient() ModbusClient::~ModbusClient()
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusClient::setTimeout( timeout_t msec ) void ModbusClient::setTimeout( timeout_t msec )
{ {
replyTimeOut_ms = msec; replyTimeOut_ms = msec;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
int ModbusClient::setAfterSendPause( timeout_t msec ) int ModbusClient::setAfterSendPause( timeout_t msec )
{ {
timeout_t old = aftersend_msec; timeout_t old = aftersend_msec;
aftersend_msec = msec; aftersend_msec = msec;
return old; return old;
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ReadCoilRetMessage ModbusClient::read01( ModbusAddr addr, ReadCoilRetMessage ModbusClient::read01( ModbusAddr addr,
ModbusData start, ModbusData count ) ModbusData start, ModbusData count )
{ {
ReadCoilMessage msg(addr, start, count); ReadCoilMessage msg(addr, start, count);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
ReadCoilRetMessage ret(qreply); ReadCoilRetMessage ret(qreply);
if( ret.bcnt != numBytes(count) ) if( ret.bcnt != numBytes(count) )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ReadInputStatusRetMessage ModbusClient::read02( ModbusAddr addr, ReadInputStatusRetMessage ModbusClient::read02( ModbusAddr addr,
ModbusData start, ModbusData count ) ModbusData start, ModbusData count )
{ {
ReadInputStatusMessage msg(addr, start, count); ReadInputStatusMessage msg(addr, start, count);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
ReadInputStatusRetMessage ret(qreply); ReadInputStatusRetMessage ret(qreply);
if( ret.bcnt != numBytes(count) ) if( ret.bcnt != numBytes(count) )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ReadOutputRetMessage ModbusClient::read03( ModbusAddr addr, ReadOutputRetMessage ModbusClient::read03( ModbusAddr addr,
ModbusData start, ModbusData count ) ModbusData start, ModbusData count )
{ {
ReadOutputMessage msg(addr, start, count); ReadOutputMessage msg(addr, start, count);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
ReadOutputRetMessage ret(qreply); ReadOutputRetMessage ret(qreply);
if( ret.count != count ) if( ret.count != count )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ReadInputRetMessage ModbusClient::read04( ModbusAddr addr, ReadInputRetMessage ModbusClient::read04( ModbusAddr addr,
ModbusData start, ModbusData count ) ModbusData start, ModbusData count )
{ {
ReadInputMessage msg(addr, start, count); ReadInputMessage msg(addr, start, count);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
ReadInputRetMessage ret(qreply); ReadInputRetMessage ret(qreply);
if( ret.count != count ) if( ret.count != count )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ForceSingleCoilRetMessage ModbusClient::write05( ModbusAddr addr, ForceSingleCoilRetMessage ModbusClient::write05( ModbusAddr addr,
ModbusData start, bool cmd ) ModbusData start, bool cmd )
{ {
ForceSingleCoilMessage msg(addr, start, cmd); ForceSingleCoilMessage msg(addr, start, cmd);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
ForceSingleCoilRetMessage ret(qreply); ForceSingleCoilRetMessage ret(qreply);
if( ret.start != start ) if( ret.start != start )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
if( ret.cmd() != cmd ) if( ret.cmd() != cmd )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
WriteSingleOutputRetMessage ModbusClient::write06( ModbusAddr addr, WriteSingleOutputRetMessage ModbusClient::write06( ModbusAddr addr,
ModbusData start, ModbusData data ) ModbusData start, ModbusData data )
{ {
WriteSingleOutputMessage msg(addr, start, data); WriteSingleOutputMessage msg(addr, start, data);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
WriteSingleOutputRetMessage ret(qreply); WriteSingleOutputRetMessage ret(qreply);
if( ret.start != start ) if( ret.start != start )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
if( ret.data != data ) if( ret.data != data )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ForceCoilsRetMessage ModbusClient::write0F( ForceCoilsMessage& msg ) ForceCoilsRetMessage ModbusClient::write0F( ForceCoilsMessage& msg )
{ {
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
ForceCoilsRetMessage ret(qreply); ForceCoilsRetMessage ret(qreply);
if( ret.start != msg.start ) if( ret.start != msg.start )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
if( ret.quant != msg.quant ) if( ret.quant != msg.quant )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
WriteOutputRetMessage ModbusClient::write10( WriteOutputMessage& msg ) WriteOutputRetMessage ModbusClient::write10( WriteOutputMessage& msg )
{ {
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
WriteOutputRetMessage ret(qreply); WriteOutputRetMessage ret(qreply);
if( ret.start != msg.start ) if( ret.start != msg.start )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
if( ret.quant != msg.quant ) if( ret.quant != msg.quant )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
DiagnosticRetMessage ModbusClient::diag08( ModbusAddr addr, DiagnosticRetMessage ModbusClient::diag08( ModbusAddr addr,
DiagnosticsSubFunction subfunc, DiagnosticsSubFunction subfunc,
ModbusRTU::ModbusData dat ) ModbusRTU::ModbusData dat )
{ {
DiagnosticMessage msg(addr, subfunc, dat); DiagnosticMessage msg(addr, subfunc, dat);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
DiagnosticRetMessage ret(qreply); DiagnosticRetMessage ret(qreply);
if( ret.subf != subfunc ) if( ret.subf != subfunc )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ModbusRTU::MEIMessageRetRDI ModbusClient::read4314( ModbusRTU::ModbusAddr addr, ModbusRTU::MEIMessageRetRDI ModbusClient::read4314( ModbusRTU::ModbusAddr addr,
ModbusRTU::ModbusByte devID, ModbusRTU::ModbusByte devID,
ModbusRTU::ModbusByte objID ) ModbusRTU::ModbusByte objID )
{ {
MEIMessageRDI msg(addr, devID, objID); MEIMessageRDI msg(addr, devID, objID);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(msg.addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
{ {
MEIMessageRetRDI ret(qreply); MEIMessageRetRDI ret(qreply);
if( ret.devID != devID ) if( ret.devID != devID )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
if( ret.objID != objID ) if( ret.objID != objID )
throw mbException(erBadDataValue); throw mbException(erBadDataValue);
return ret; return ret;
} }
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
SetDateTimeRetMessage ModbusClient::setDateTime( ModbusAddr addr, ModbusByte hour, ModbusByte min, ModbusByte sec, SetDateTimeRetMessage ModbusClient::setDateTime( ModbusAddr addr, ModbusByte hour, ModbusByte min, ModbusByte sec,
ModbusByte day, ModbusByte mon, ModbusByte year, ModbusByte day, ModbusByte mon, ModbusByte year,
ModbusByte century ) ModbusByte century )
{ {
SetDateTimeMessage msg(addr); SetDateTimeMessage msg(addr);
msg.hour = hour; msg.hour = hour;
msg.min = min; msg.min = min;
msg.sec = sec; msg.sec = sec;
msg.day = day; msg.day = day;
msg.mon = mon; msg.mon = mon;
msg.year = year; msg.year = year;
msg.century = century; msg.century = century;
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms); mbErrCode res = query(addr, qbuf, qreply, replyTimeOut_ms);
if( res == erNoError ) if( res == erNoError )
return SetDateTimeRetMessage(qreply); return SetDateTimeRetMessage(qreply);
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
void ModbusClient::fileTransfer(ModbusAddr addr, ModbusData numfile, void ModbusClient::fileTransfer(ModbusAddr addr, ModbusData numfile,
const std::string& save2filename, timeout_t part_timeout_msec ) const std::string& save2filename, timeout_t part_timeout_msec )
{ {
//#warning Необходимо реализовать //#warning Необходимо реализовать
// throw mbException(erUnExpectedPacketType); // throw mbException(erUnExpectedPacketType);
mbErrCode res = erNoError; mbErrCode res = erNoError;
FILE* fdsave = fopen(save2filename.c_str(), "w"); FILE* fdsave = fopen(save2filename.c_str(), "w");
if( fdsave == NULL ) if( fdsave == NULL )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(fileTransfer): fopen '" dlog->warn() << "(fileTransfer): fopen '"
<< save2filename << "' with error: " << save2filename << "' with error: "
<< strerror(errno) << endl; << strerror(errno) << endl;
throw mbException(erHardwareError); throw mbException(erHardwareError);
} }
uint16_t maxpackets = 65535; uint16_t maxpackets = 65535;
uint16_t curpack = 0; uint16_t curpack = 0;
PassiveTimer ptTimeout(part_timeout_msec); PassiveTimer ptTimeout(part_timeout_msec);
while( curpack < maxpackets && !ptTimeout.checkTime() ) while( curpack < maxpackets && !ptTimeout.checkTime() )
{ {
try try
{ {
FileTransferRetMessage ret = partOfFileTransfer( addr, numfile, curpack, part_timeout_msec ); FileTransferRetMessage ret = partOfFileTransfer( addr, numfile, curpack, part_timeout_msec );
if( ret.numfile != numfile ) if( ret.numfile != numfile )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(fileTransfer): recv nfile=" << ret.numfile dlog->warn() << "(fileTransfer): recv nfile=" << ret.numfile
<< " !=numfile(" << numfile << ")" << endl; << " !=numfile(" << numfile << ")" << endl;
continue; continue;
} }
if( ret.packet != curpack ) if( ret.packet != curpack )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(fileTransfer): recv npack=" << ret.packet dlog->warn() << "(fileTransfer): recv npack=" << ret.packet
<< " !=curpack(" << curpack << ")" << endl; << " !=curpack(" << curpack << ")" << endl;
continue; continue;
} }
maxpackets = ret.numpacks; maxpackets = ret.numpacks;
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(fileTransfer): maxpackets=" dlog->info() << "(fileTransfer): maxpackets="
<< ret.numpacks << " curpack=" << curpack + 1 << endl; << ret.numpacks << " curpack=" << curpack + 1 << endl;
// save data... // save data...
if( fwrite(&ret.data, ret.dlen, 1, fdsave) <= 0 ) if( fwrite(&ret.data, ret.dlen, 1, fdsave) <= 0 )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(fileTransfer): fwrite '" dlog->warn() << "(fileTransfer): fwrite '"
<< save2filename << "' with error: " << save2filename << "' with error: "
<< strerror(errno) << endl; << strerror(errno) << endl;
res = erHardwareError; res = erHardwareError;
break; break;
} }
ptTimeout.reset(); ptTimeout.reset();
curpack = ret.packet + 1; // curpack++; curpack = ret.packet + 1; // curpack++;
} }
catch( mbException& ex ) catch( mbException& ex )
{ {
if( ex.err == erBadCheckSum ) if( ex.err == erBadCheckSum )
continue; continue;
res = ex.err; res = ex.err;
break; break;
} }
} }
fclose(fdsave); fclose(fdsave);
if( curpack == maxpackets ) if( curpack == maxpackets )
return; return;
if( res == erNoError ) if( res == erNoError )
res = erTimeOut; res = erTimeOut;
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
FileTransferRetMessage ModbusClient::partOfFileTransfer( ModbusAddr addr, FileTransferRetMessage ModbusClient::partOfFileTransfer( ModbusAddr addr,
ModbusData idFile, ModbusData numpack, ModbusData idFile, ModbusData numpack,
timeout_t part_timeout_msec ) timeout_t part_timeout_msec )
{ {
FileTransferMessage msg(addr, idFile, numpack); FileTransferMessage msg(addr, idFile, numpack);
qbuf = msg.transport_msg(); qbuf = msg.transport_msg();
mbErrCode res = query(addr, qbuf, qreply, part_timeout_msec); mbErrCode res = query(addr, qbuf, qreply, part_timeout_msec);
if( res == erNoError ) if( res == erNoError )
return FileTransferRetMessage(qreply); return FileTransferRetMessage(qreply);
throw mbException(res); throw mbException(res);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
mbErrCode ModbusClient::recv( ModbusAddr addr, ModbusByte qfunc, mbErrCode ModbusClient::recv( ModbusAddr addr, ModbusByte qfunc,
ModbusMessage& rbuf, timeout_t timeout ) ModbusMessage& rbuf, timeout_t timeout )
{ {
if( timeout == UniSetTimer::WaitUpTime ) if( timeout == UniSetTimer::WaitUpTime )
timeout = 15 * 60 * 1000 * 1000; // используем просто большое время (15 минут). Переведя его в наносекунды. timeout = 15 * 60 * 1000 * 1000; // используем просто большое время (15 минут). Переведя его в наносекунды.
setChannelTimeout(timeout); setChannelTimeout(timeout);
PassiveTimer tmAbort(timeout); PassiveTimer tmAbort(timeout);
size_t bcnt = 0; // receive bytes count size_t bcnt = 0; // receive bytes count
try try
{ {
bool begin = false; bool begin = false;
while( !tmAbort.checkTime() ) while( !tmAbort.checkTime() )
{ {
bcnt = getNextData((unsigned char*)(&rbuf.pduhead.addr), sizeof(rbuf.pduhead.addr)); bcnt = getNextData((unsigned char*)(&rbuf.pduhead.addr), sizeof(rbuf.pduhead.addr));
if( bcnt > 0 && ( rbuf.addr() == addr ) ) // || (onBroadcast && rbuf.addr==BroadcastAddr) ) ) if( bcnt > 0 && ( rbuf.addr() == addr ) ) // || (onBroadcast && rbuf.addr==BroadcastAddr) ) )
{ {
begin = true; begin = true;
break; break;
} }
std::this_thread::sleep_for(std::chrono::microseconds(sleepPause_usec)); std::this_thread::sleep_for(std::chrono::microseconds(sleepPause_usec));
} }
if( !begin ) if( !begin )
return erTimeOut; return erTimeOut;
/*! \todo Подумать Может стоит всё-таки получать весь пакет, а проверять кому он адресован на уровне выше?! /*! \todo Подумать Может стоит всё-таки получать весь пакет, а проверять кому он адресован на уровне выше?!
// Lav: конечно стоит, нам же надо буфер чистить // Lav: конечно стоит, нам же надо буфер чистить
*/ */
// Проверка кому адресован пакет... // Проверка кому адресован пакет...
if( rbuf.addr() != addr && rbuf.addr() != BroadcastAddr ) if( rbuf.addr() != addr && rbuf.addr() != BroadcastAddr )
{ {
ostringstream err; ostringstream err;
err << "(recv): BadNodeAddress. my= " << addr2str(addr) err << "(recv): BadNodeAddress. my= " << addr2str(addr)
<< " msg.addr=" << addr2str(rbuf.addr()); << " msg.addr=" << addr2str(rbuf.addr());
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
cleanupChannel(); cleanupChannel();
return erBadReplyNodeAddress; return erBadReplyNodeAddress;
} }
return recv_pdu(qfunc, rbuf, timeout); return recv_pdu(qfunc, rbuf, timeout);
} }
catch( const uniset::TimeOut& ex ) catch( const uniset::TimeOut& ex )
{ {
// cout << "(recv): catch TimeOut " << endl; // cout << "(recv): catch TimeOut " << endl;
} }
catch( const uniset::CommFailed& ex ) catch( const uniset::CommFailed& ex )
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(recv): " << ex << endl; dlog->crit() << "(recv): " << ex << endl;
cleanupChannel(); cleanupChannel();
return erTimeOut; return erTimeOut;
} }
catch( const uniset::Exception& ex ) // SystemError catch( const uniset::Exception& ex ) // SystemError
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(recv): " << ex << endl; dlog->crit() << "(recv): " << ex << endl;
cleanupChannel(); cleanupChannel();
return erHardwareError; return erHardwareError;
} }
return erTimeOut; return erTimeOut;
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
mbErrCode ModbusClient::recv_pdu( ModbusByte qfunc, ModbusMessage& rbuf, timeout_t timeout ) mbErrCode ModbusClient::recv_pdu( ModbusByte qfunc, ModbusMessage& rbuf, timeout_t timeout )
{ {
size_t bcnt = 1; // receive bytes count (1 - addr) size_t bcnt = 1; // receive bytes count (1 - addr)
try try
{ {
// ----------------------------------- // -----------------------------------
tmProcessing.setTiming(replyTimeOut_ms); tmProcessing.setTiming(replyTimeOut_ms);
// recv func number // recv func number
size_t k = getNextData((unsigned char*)(&rbuf.pduhead.func), sizeof(rbuf.pduhead.func)); size_t k = getNextData((unsigned char*)(&rbuf.pduhead.func), sizeof(rbuf.pduhead.func));
if( k < sizeof(rbuf.pduhead.func) ) if( k < sizeof(rbuf.pduhead.func) )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(recv): receive " << k << " bytes < " << sizeof(rbuf.pduhead.func) << endl; dlog->warn() << "(recv): receive " << k << " bytes < " << sizeof(rbuf.pduhead.func) << endl;
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += k; bcnt += k;
rbuf.dlen = 0; rbuf.dlen = 0;
if( dlog->is_level9() ) if( dlog->is_level9() )
dlog->level9() << "(recv): PDU: " << rbuf.pduhead << endl; dlog->level9() << "(recv): PDU: " << rbuf.pduhead << endl;
// обработка сообщения об ошибке... // обработка сообщения об ошибке...
if( rbuf.func() == (qfunc | MBErrMask) ) if( rbuf.func() == (qfunc | MBErrMask) )
{ {
rbuf.dlen = ErrorRetMessage::szData(); rbuf.dlen = ErrorRetMessage::szData();
if( crcNoCheckit ) if( crcNoCheckit )
rbuf.dlen -= szCRC; rbuf.dlen -= szCRC;
size_t rlen = getNextData((unsigned char*)(&(rbuf.data)), rbuf.dlen); size_t rlen = getNextData((unsigned char*)(&(rbuf.data)), rbuf.dlen);
if( rlen < rbuf.dlen ) if( rlen < rbuf.dlen )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(recv:Error): buf: " << rbuf << endl; dlog->warn() << "(recv:Error): buf: " << rbuf << endl;
dlog->warn() << "(recv:Error)(" << rbuf.func() dlog->warn() << "(recv:Error)(" << rbuf.func()
<< "): Получили данных меньше чем ждали...(recv=" << "): Получили данных меньше чем ждали...(recv="
<< rlen << " < wait=" << rbuf.dlen << ")" << endl; << rlen << " < wait=" << rbuf.dlen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen; bcnt += rlen;
ErrorRetMessage em(rbuf); ErrorRetMessage em(rbuf);
if( !crcNoCheckit ) if( !crcNoCheckit )
{ {
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != em.crc ) if( tcrc != em.crc )
{ {
ostringstream err; ostringstream err;
err << "(recv:error): bad crc. calc.crc=" << dat2str(tcrc) err << "(recv:error): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(em.crc); << " msg.crc=" << dat2str(em.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
} }
return (mbErrCode)em.ecode; return (mbErrCode)em.ecode;
} }
if( qfunc != rbuf.func() ) if( qfunc != rbuf.func() )
{ {
cleanupChannel(); cleanupChannel();
return erUnExpectedPacketType; return erUnExpectedPacketType;
} }
// Определяем тип сообщения // Определяем тип сообщения
switch( rbuf.func() ) switch( rbuf.func() )
{ {
case fnReadCoilStatus: case fnReadCoilStatus:
rbuf.dlen = ReadCoilRetMessage::szHead(); rbuf.dlen = ReadCoilRetMessage::szHead();
break; break;
case fnReadInputStatus: case fnReadInputStatus:
rbuf.dlen = ReadInputStatusRetMessage::szHead(); rbuf.dlen = ReadInputStatusRetMessage::szHead();
break; break;
case fnReadOutputRegisters: case fnReadOutputRegisters:
rbuf.dlen = ReadOutputRetMessage::szHead(); rbuf.dlen = ReadOutputRetMessage::szHead();
break; break;
case fnReadInputRegisters: case fnReadInputRegisters:
rbuf.dlen = ReadInputRetMessage::szHead(); rbuf.dlen = ReadInputRetMessage::szHead();
break; break;
case fnForceMultipleCoils: case fnForceMultipleCoils:
rbuf.dlen = ForceCoilsRetMessage::szData(); rbuf.dlen = ForceCoilsRetMessage::szData();
if( crcNoCheckit ) if( crcNoCheckit )
rbuf.dlen -= szCRC; rbuf.dlen -= szCRC;
break; break;
case fnWriteOutputRegisters: case fnWriteOutputRegisters:
rbuf.dlen = WriteOutputRetMessage::szData(); rbuf.dlen = WriteOutputRetMessage::szData();
if( crcNoCheckit ) if( crcNoCheckit )
rbuf.dlen -= szCRC; rbuf.dlen -= szCRC;
break; break;
case fnWriteOutputSingleRegister: case fnWriteOutputSingleRegister:
rbuf.dlen = WriteSingleOutputRetMessage::szData(); rbuf.dlen = WriteSingleOutputRetMessage::szData();
if( crcNoCheckit ) if( crcNoCheckit )
rbuf.dlen -= szCRC; rbuf.dlen -= szCRC;
break; break;
case fnForceSingleCoil: case fnForceSingleCoil:
rbuf.dlen = ForceSingleCoilRetMessage::szData(); rbuf.dlen = ForceSingleCoilRetMessage::szData();
if( crcNoCheckit ) if( crcNoCheckit )
rbuf.dlen -= szCRC; rbuf.dlen -= szCRC;
break; break;
case fnDiagnostics: case fnDiagnostics:
rbuf.dlen = DiagnosticRetMessage::szHead(); rbuf.dlen = DiagnosticRetMessage::szHead();
break; break;
case fnMEI: case fnMEI:
rbuf.dlen = MEIMessageRetRDI::szHead(); rbuf.dlen = MEIMessageRetRDI::szHead();
break; break;
case fnSetDateTime: case fnSetDateTime:
rbuf.dlen = SetDateTimeRetMessage::szData(); rbuf.dlen = SetDateTimeRetMessage::szData();
if( crcNoCheckit ) if( crcNoCheckit )
rbuf.dlen -= szCRC; rbuf.dlen -= szCRC;
break; break;
case fnFileTransfer: case fnFileTransfer:
rbuf.dlen = FileTransferRetMessage::szHead(); rbuf.dlen = FileTransferRetMessage::szHead();
break; break;
/* /*
case fnJournalCommand: case fnJournalCommand:
rbuf.len = JournalCommandMessage::szData(); rbuf.len = JournalCommandMessage::szData();
break; break;
case fnRemoteService: case fnRemoteService:
rbuf.len = RemoteServiceMessage::szHead(); rbuf.len = RemoteServiceMessage::szHead();
break; break;
*/ */
default: default:
cleanupChannel(); cleanupChannel();
return erUnExpectedPacketType; return erUnExpectedPacketType;
} }
// Получаем остальную часть сообщения // Получаем остальную часть сообщения
size_t rlen = getNextData((unsigned char*)(rbuf.data), rbuf.dlen); size_t rlen = getNextData((unsigned char*)(rbuf.data), rbuf.dlen);
if( rlen < rbuf.dlen ) if( rlen < rbuf.dlen )
{ {
// rbuf.len = bcnt + rlen - szModbusHeader; // rbuf.len = bcnt + rlen - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(recv): buf: " << rbuf << endl; dlog->warn() << "(recv): buf: " << rbuf << endl;
dlog->warn() << "(recv)(" << rbuf.func() dlog->warn() << "(recv)(" << rbuf.func()
<< "): Получили данных меньше чем ждали...(recv=" << "): Получили данных меньше чем ждали...(recv="
<< rlen << " < wait=" << rbuf.dlen << ")" << endl; << rlen << " < wait=" << rbuf.dlen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen; bcnt += rlen;
// получаем остальное... // получаем остальное...
if( rbuf.func() == fnReadCoilStatus ) if( rbuf.func() == fnReadCoilStatus )
{ {
int szDataLen = ReadCoilRetMessage::getDataLen(rbuf) + szCRC; int szDataLen = ReadCoilRetMessage::getDataLen(rbuf) + szCRC;
if( crcNoCheckit ) if( crcNoCheckit )
szDataLen -= szCRC; szDataLen -= szCRC;
// Мы получили только предварительный загловок // Мы получили только предварительный загловок
// Теперь необходимо дополучить данные // Теперь необходимо дополучить данные
// (c позиции rlen, т.к. часть уже получили) // (c позиции rlen, т.к. часть уже получили)
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x01): buf: " << rbuf << endl; dlog->warn() << "(0x01): buf: " << rbuf << endl;
dlog->warn() << "(0x01)(" dlog->warn() << "(0x01)("
<< (int)rbuf.func() << "):(fnReadCoilStatus) " << (int)rbuf.func() << "):(fnReadCoilStatus) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
ReadCoilRetMessage mRead(rbuf); ReadCoilRetMessage mRead(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x01)(fnReadCoilStatus): recv buf: " << rbuf << endl; dlog->info() << "(0x01)(fnReadCoilStatus): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mRead.crc ) if( tcrc != mRead.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x01)(fnReadCoilStatus): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x01)(fnReadCoilStatus): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRead.crc); << " msg.crc=" << dat2str(mRead.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnReadInputStatus ) else if( rbuf.func() == fnReadInputStatus )
{ {
int szDataLen = ReadInputStatusRetMessage::getDataLen(rbuf) + szCRC; int szDataLen = ReadInputStatusRetMessage::getDataLen(rbuf) + szCRC;
if( crcNoCheckit ) if( crcNoCheckit )
szDataLen -= szCRC; szDataLen -= szCRC;
// Мы получили только предварительный загловок // Мы получили только предварительный загловок
// Теперь необходимо дополучить данные // Теперь необходимо дополучить данные
// (c позиции rlen, т.к. часть уже получили) // (c позиции rlen, т.к. часть уже получили)
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x02): buf: " << rbuf << endl; dlog->warn() << "(0x02): buf: " << rbuf << endl;
dlog->warn() << "(0x02)(" dlog->warn() << "(0x02)("
<< (int)rbuf.func() << "):(fnReadInputStatus) " << (int)rbuf.func() << "):(fnReadInputStatus) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
ReadInputStatusRetMessage mRead(rbuf); ReadInputStatusRetMessage mRead(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x02)(fnReadInputStatus): recv buf: " << rbuf << endl; dlog->info() << "(0x02)(fnReadInputStatus): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mRead.crc ) if( tcrc != mRead.crc )
{ {
ostringstream err; ostringstream err;
err << "(recv:fnReadInputStatus): bad crc. calc.crc=" << dat2str(tcrc) err << "(recv:fnReadInputStatus): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRead.crc); << " msg.crc=" << dat2str(mRead.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnReadInputRegisters ) else if( rbuf.func() == fnReadInputRegisters )
{ {
int szDataLen = ReadInputRetMessage::getDataLen(rbuf) + szCRC; int szDataLen = ReadInputRetMessage::getDataLen(rbuf) + szCRC;
if( crcNoCheckit ) if( crcNoCheckit )
szDataLen -= szCRC; szDataLen -= szCRC;
// Мы получили только предварительный загловок // Мы получили только предварительный загловок
// Теперь необходимо дополучить данные // Теперь необходимо дополучить данные
// (c позиции rlen, т.к. часть уже получили) // (c позиции rlen, т.к. часть уже получили)
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x04): buf: " << rbuf << endl; dlog->warn() << "(0x04): buf: " << rbuf << endl;
dlog->warn() << "(0x04)(" dlog->warn() << "(0x04)("
<< (int)rbuf.func() << "):(fnReadInputRegisters) " << (int)rbuf.func() << "):(fnReadInputRegisters) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
ReadInputRetMessage mRead(rbuf); ReadInputRetMessage mRead(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(recv)(fnReadInputRegisters): recv buf: " << rbuf << endl; dlog->info() << "(recv)(fnReadInputRegisters): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mRead.crc ) if( tcrc != mRead.crc )
{ {
ostringstream err; ostringstream err;
err << "(recv:fnReadInputRegisters): bad crc. calc.crc=" << dat2str(tcrc) err << "(recv:fnReadInputRegisters): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRead.crc); << " msg.crc=" << dat2str(mRead.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnReadOutputRegisters ) else if( rbuf.func() == fnReadOutputRegisters )
{ {
int szDataLen = ReadOutputRetMessage::getDataLen(rbuf) + szCRC; int szDataLen = ReadOutputRetMessage::getDataLen(rbuf) + szCRC;
if( crcNoCheckit ) if( crcNoCheckit )
szDataLen -= szCRC; szDataLen -= szCRC;
// Мы получили только предварительный загловок // Мы получили только предварительный загловок
// Теперь необходимо дополучить данные // Теперь необходимо дополучить данные
// (c позиции rlen, т.к. часть уже получили) // (c позиции rlen, т.к. часть уже получили)
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x03): buf: " << rbuf << endl; dlog->warn() << "(0x03): buf: " << rbuf << endl;
dlog->warn() << "(0x03)(" dlog->warn() << "(0x03)("
<< (int)rbuf.func() << "):(fnReadInputRegisters) " << (int)rbuf.func() << "):(fnReadInputRegisters) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
ReadOutputRetMessage mRead(rbuf); ReadOutputRetMessage mRead(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(recv)(fnReadOutputRegisters): recv buf: " << rbuf << endl; dlog->info() << "(recv)(fnReadOutputRegisters): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mRead.crc ) if( tcrc != mRead.crc )
{ {
ostringstream err; ostringstream err;
err << "(recv:fnReadOutputRegisters): bad crc. calc.crc=" << dat2str(tcrc) err << "(recv:fnReadOutputRegisters): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRead.crc); << " msg.crc=" << dat2str(mRead.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnForceMultipleCoils ) else if( rbuf.func() == fnForceMultipleCoils )
{ {
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
ForceCoilsRetMessage mWrite(rbuf); ForceCoilsRetMessage mWrite(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x0F): recv buf: " << rbuf << endl; dlog->info() << "(0x0F): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mWrite.crc ) if( tcrc != mWrite.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x0F): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x0F): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mWrite.crc); << " msg.crc=" << dat2str(mWrite.crc);
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnWriteOutputRegisters ) else if( rbuf.func() == fnWriteOutputRegisters )
{ {
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
WriteOutputRetMessage mWrite(rbuf); WriteOutputRetMessage mWrite(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x10): recv buf: " << rbuf << endl; dlog->info() << "(0x10): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mWrite.crc ) if( tcrc != mWrite.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x10): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x10): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mWrite.crc); << " msg.crc=" << dat2str(mWrite.crc);
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnWriteOutputSingleRegister ) else if( rbuf.func() == fnWriteOutputSingleRegister )
{ {
WriteSingleOutputRetMessage mWrite(rbuf); WriteSingleOutputRetMessage mWrite(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x06): recv buf: " << rbuf << endl; dlog->info() << "(0x06): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead() + mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead() + mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mWrite.crc ) if( tcrc != mWrite.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x06): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x06): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mWrite.crc); << " msg.crc=" << dat2str(mWrite.crc);
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnForceSingleCoil ) else if( rbuf.func() == fnForceSingleCoil )
{ {
ForceSingleCoilRetMessage mWrite(rbuf); ForceSingleCoilRetMessage mWrite(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x05): recv buf: " << rbuf << endl; dlog->info() << "(0x05): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead() + mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead() + mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mWrite.crc ) if( tcrc != mWrite.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x05): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x05): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mWrite.crc); << " msg.crc=" << dat2str(mWrite.crc);
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnDiagnostics ) else if( rbuf.func() == fnDiagnostics )
{ {
int szDataLen = DiagnosticRetMessage::getDataLen(rbuf) + szCRC; int szDataLen = DiagnosticRetMessage::getDataLen(rbuf) + szCRC;
if( crcNoCheckit ) if( crcNoCheckit )
szDataLen -= szCRC; szDataLen -= szCRC;
// Мы получили только предварительный загловок // Мы получили только предварительный загловок
// Теперь необходимо дополучить данные // Теперь необходимо дополучить данные
// (c позиции rlen, т.к. часть уже получили) // (c позиции rlen, т.к. часть уже получили)
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x08): buf: " << rbuf << endl; dlog->warn() << "(0x08): buf: " << rbuf << endl;
dlog->warn() << "(0x08)(" dlog->warn() << "(0x08)("
<< (int)rbuf.func() << "):(fnDiagnostics) " << (int)rbuf.func() << "):(fnDiagnostics) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
DiagnosticRetMessage mDiag(rbuf); DiagnosticRetMessage mDiag(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(recv)(fnDiagnostics): recv buf: " << rbuf << endl; dlog->info() << "(recv)(fnDiagnostics): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mDiag.crc ) if( tcrc != mDiag.crc )
{ {
ostringstream err; ostringstream err;
err << "(recv:fnDiagnostics): bad crc. calc.crc=" << dat2str(tcrc) err << "(recv:fnDiagnostics): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mDiag.crc); << " msg.crc=" << dat2str(mDiag.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnMEI ) else if( rbuf.func() == fnMEI )
{ {
MEIMessageRetRDI mPreRDI; MEIMessageRetRDI mPreRDI;
mPreRDI.pre_init(rbuf); mPreRDI.pre_init(rbuf);
if( mPreRDI.objNum > 0 ) if( mPreRDI.objNum > 0 )
{ {
size_t onum = 0; size_t onum = 0;
while( (rlen + 2) < sizeof(rbuf.data) && onum < mPreRDI.objNum ) while( (rlen + 2) < sizeof(rbuf.data) && onum < mPreRDI.objNum )
{ {
// сперва получаем два байта, для определения длины последующих данных // сперва получаем два байта, для определения длины последующих данных
size_t szDataLen = 2; // object id + len size_t szDataLen = 2; // object id + len
size_t rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); size_t rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x2B/0x0E): buf: " << rbuf << endl; dlog->warn() << "(0x2B/0x0E): buf: " << rbuf << endl;
dlog->warn() << "(0x2B/0x0E)(" dlog->warn() << "(0x2B/0x0E)("
<< (int)rbuf.func() << "):(fnMEI) " << (int)rbuf.func() << "):(fnMEI) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
rlen += szDataLen; rlen += szDataLen;
bcnt += szDataLen; bcnt += szDataLen;
// теперь получаем собственно данные // теперь получаем собственно данные
szDataLen = rbuf.data[rlen - 1]; // последний (предыдущий) байт - это длина данных szDataLen = rbuf.data[rlen - 1]; // последний (предыдущий) байт - это длина данных
rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x2B/0x0E): buf: " << rbuf << endl; dlog->warn() << "(0x2B/0x0E): buf: " << rbuf << endl;
dlog->warn() << "(0x2B/0x0E)(" dlog->warn() << "(0x2B/0x0E)("
<< (int)rbuf.func() << "):(fnMEI) " << (int)rbuf.func() << "):(fnMEI) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
rlen += szDataLen; rlen += szDataLen;
bcnt += szDataLen; bcnt += szDataLen;
onum++; onum++;
} }
} }
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
if( crcNoCheckit ) if( crcNoCheckit )
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(recv)(fnMEI): recv buf: " << rbuf << endl; dlog->info() << "(recv)(fnMEI): recv buf: " << rbuf << endl;
return erNoError; return erNoError;
} }
// теперь получаем CRC // теперь получаем CRC
size_t rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szCRC); size_t rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szCRC);
if( rlen1 < szCRC ) if( rlen1 < szCRC )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x2B/0x0E): buf: " << rbuf << endl; dlog->warn() << "(0x2B/0x0E): buf: " << rbuf << endl;
dlog->warn() << "(0x2B/0x0E)(" dlog->warn() << "(0x2B/0x0E)("
<< (int)rbuf.func() << "):(fnMEI) " << (int)rbuf.func() << "):(fnMEI) "
<< "(CRC): Получили данных меньше чем ждали...(" << "(CRC): Получили данных меньше чем ждали...("
<< rlen1 << " < " << szCRC << ")" << endl; << rlen1 << " < " << szCRC << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(recv)(fnMEI): recv buf: " << rbuf << endl; dlog->info() << "(recv)(fnMEI): recv buf: " << rbuf << endl;
MEIMessageRetRDI mRDI(rbuf); MEIMessageRetRDI mRDI(rbuf);
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mRDI.crc ) if( tcrc != mRDI.crc )
{ {
ostringstream err; ostringstream err;
err << "(recv:fnMEI): bad crc. calc.crc=" << dat2str(tcrc) err << "(recv:fnMEI): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRDI.crc); << " msg.crc=" << dat2str(mRDI.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnSetDateTime ) else if( rbuf.func() == fnSetDateTime )
{ {
SetDateTimeRetMessage mSet(rbuf); SetDateTimeRetMessage mSet(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x50): recv buf: " << rbuf << endl; dlog->info() << "(0x50): recv buf: " << rbuf << endl;
if( !crcNoCheckit ) if( !crcNoCheckit )
{ {
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) и до конца (исключив последний элемент содержащий CRC) // от начала(включая заголовок) и до конца (исключив последний элемент содержащий CRC)
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mSet.crc ) if( tcrc != mSet.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x50): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x50): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mSet.crc); << " msg.crc=" << dat2str(mSet.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
} }
if( !mSet.checkFormat() ) if( !mSet.checkFormat() )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(0x50): некорректные значения..." << endl; dlog->warn() << "(0x50): некорректные значения..." << endl;
return erBadDataValue; // return erInvalidFormat; return erBadDataValue; // return erInvalidFormat;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnFileTransfer ) else if( rbuf.func() == fnFileTransfer )
{ {
int szDataLen = FileTransferRetMessage::getDataLen(rbuf) + szCRC; int szDataLen = FileTransferRetMessage::getDataLen(rbuf) + szCRC;
if( crcNoCheckit ) if( crcNoCheckit )
szDataLen -= szCRC; szDataLen -= szCRC;
// Мы получили только предварительный загловок // Мы получили только предварительный загловок
// Теперь необходимо дополучить данные // Теперь необходимо дополучить данные
// (c позиции rlen, т.к. часть уже получили) // (c позиции rlen, т.к. часть уже получили)
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.dlen = bcnt + rlen1 - szModbusHeader; rbuf.dlen = bcnt + rlen1 - szModbusHeader;
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
dlog->warn() << "(0x66): buf: " << rbuf << endl; dlog->warn() << "(0x66): buf: " << rbuf << endl;
dlog->warn() << "(0x66)(" dlog->warn() << "(0x66)("
<< rbuf.func() << "):(fnFileTransfer) " << rbuf.func() << "):(fnFileTransfer) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
} }
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.dlen = bcnt - szModbusHeader; rbuf.dlen = bcnt - szModbusHeader;
FileTransferRetMessage mFT(rbuf); FileTransferRetMessage mFT(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x66): recv buf: " << rbuf << endl; dlog->info() << "(0x66): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mFT.crc ) if( tcrc != mFT.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x66): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x66): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mFT.crc); << " msg.crc=" << dat2str(mFT.crc);
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
#if 0 #if 0
else if( rbuf.func() == fnJournalCommand ) else if( rbuf.func() == fnJournalCommand )
{ {
JournalCommandMessage mRead(rbuf); JournalCommandMessage mRead(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x65): recv buf: " << rbuf << endl; dlog->info() << "(0x65): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) и до конца (исключив последний элемент содержащий CRC) // от начала(включая заголовок) и до конца (исключив последний элемент содержащий CRC)
// ModbusData tcrc = checkCRC((ModbusByte*)(&rbuf.pduhead),sizeof(ReadOutputMessage)-szCRC); // ModbusData tcrc = checkCRC((ModbusByte*)(&rbuf.pduhead),sizeof(ReadOutputMessage)-szCRC);
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mRead.crc ) if( tcrc != mRead.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x65): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x65): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRead.crc); << " msg.crc=" << dat2str(mRead.crc);
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
else if( rbuf.func() == fnRemoteService ) else if( rbuf.func() == fnRemoteService )
{ {
int szDataLen = RemoteServiceMessage::getDataLen(rbuf) + szCRC; int szDataLen = RemoteServiceMessage::getDataLen(rbuf) + szCRC;
if( crcNoCheckit ) if( crcNoCheckit )
szDataLen -= szCRC; szDataLen -= szCRC;
// Мы получили только предварительный загловок // Мы получили только предварительный загловок
// Теперь необходимо дополучить данные // Теперь необходимо дополучить данные
// (c позиции rlen, т.к. часть уже получили) // (c позиции rlen, т.к. часть уже получили)
int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen); int rlen1 = getNextData((unsigned char*)(&(rbuf.data[rlen])), szDataLen);
if( rlen1 < szDataLen ) if( rlen1 < szDataLen )
{ {
rbuf.len = bcnt + rlen1 - szModbusHeader; rbuf.len = bcnt + rlen1 - szModbusHeader;
dlog->warn() << "(0x53): buf: " << rbuf << endl; dlog->warn() << "(0x53): buf: " << rbuf << endl;
dlog->warn() << "(0x53)(" dlog->warn() << "(0x53)("
<< rbuf.func() << "):(fnWriteOutputRegisters) " << rbuf.func() << "):(fnWriteOutputRegisters) "
<< "Получили данных меньше чем ждали...(" << "Получили данных меньше чем ждали...("
<< rlen1 << " < " << szDataLen << ")" << endl; << rlen1 << " < " << szDataLen << ")" << endl;
cleanupChannel(); cleanupChannel();
return erInvalidFormat; return erInvalidFormat;
} }
bcnt += rlen1; bcnt += rlen1;
rbuf.len = bcnt - szModbusHeader; rbuf.len = bcnt - szModbusHeader;
RemoteServiceMessage mRServ(rbuf); RemoteServiceMessage mRServ(rbuf);
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(0x53): recv buf: " << rbuf << endl; dlog->info() << "(0x53): recv buf: " << rbuf << endl;
if( crcNoCheckit ) if( crcNoCheckit )
return erNoError; return erNoError;
// Проверяем контрольную сумму // Проверяем контрольную сумму
// от начала(включая заголовок) // от начала(включая заголовок)
// и до конца (исключив последний элемент содержащий CRC) // и до конца (исключив последний элемент содержащий CRC)
// int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt; // int mlen = szModbusHeader + mWrite.szHead()+ mWrite.bcnt;
ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC); ModbusData tcrc = rbuf.pduCRC(bcnt - szCRC);
if( tcrc != mRServ.crc ) if( tcrc != mRServ.crc )
{ {
ostringstream err; ostringstream err;
err << "(0x53): bad crc. calc.crc=" << dat2str(tcrc) err << "(0x53): bad crc. calc.crc=" << dat2str(tcrc)
<< " msg.crc=" << dat2str(mRServ.crc); << " msg.crc=" << dat2str(mRServ.crc);
dlog->warn() << err.str() << endl; dlog->warn() << err.str() << endl;
return erBadCheckSum; return erBadCheckSum;
} }
return erNoError; return erNoError;
} }
#endif // not standart commands #endif // not standart commands
else else
{ {
// А как мы сюда добрались?!!!!!! // А как мы сюда добрались?!!!!!!
cleanupChannel(); cleanupChannel();
return erUnExpectedPacketType; return erUnExpectedPacketType;
} }
} }
catch( mbException& ex ) catch( mbException& ex )
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(recv): " << ex << endl; dlog->crit() << "(recv): " << ex << endl;
return ex.err; return ex.err;
} }
catch( const uniset::TimeOut& ex ) catch( const uniset::TimeOut& ex )
{ {
// cout << "(recv): catch TimeOut " << endl; // cout << "(recv): catch TimeOut " << endl;
} }
catch( const uniset::CommFailed& ex ) catch( const uniset::CommFailed& ex )
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(recv): " << ex << endl; dlog->crit() << "(recv): " << ex << endl;
return erTimeOut; return erTimeOut;
} }
catch( const uniset::Exception& ex ) // SystemError catch( const uniset::Exception& ex ) // SystemError
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(recv): " << ex << endl; dlog->crit() << "(recv): " << ex << endl;
return erHardwareError; return erHardwareError;
} }
return erTimeOut; return erTimeOut;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusClient::send( ModbusMessage& msg ) mbErrCode ModbusClient::send( ModbusMessage& msg )
{ {
if( msg.len() > msg.maxSizeOfMessage() ) if( msg.len() > msg.maxSizeOfMessage() )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(ModbusClient::send): message len=" << msg.len() dlog->warn() << "(ModbusClient::send): message len=" << msg.len()
<< " > MAXLEN=" << msg.maxSizeOfMessage() << endl; << " > MAXLEN=" << msg.maxSizeOfMessage() << endl;
return erPacketTooLong; return erPacketTooLong;
} }
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(ModbusClient::send): [" << msg.len() << " bytes]: " << msg << endl; dlog->info() << "(ModbusClient::send): [" << msg.len() << " bytes]: " << msg << endl;
try try
{ {
size_t len = msg.len(); // т.к. swapHead() поменяет size_t len = msg.len(); // т.к. swapHead() поменяет
msg.swapHead(); msg.swapHead();
sendData(msg.buf(), len); sendData(msg.buf(), len);
msg.swapHead(); msg.swapHead();
} }
catch( mbException& ex ) catch( mbException& ex )
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(send): " << ex << endl; dlog->crit() << "(send): " << ex << endl;
msg.swapHead(); msg.swapHead();
return ex.err; return ex.err;
} }
catch( const uniset::Exception& ex ) // SystemError catch( const uniset::Exception& ex ) // SystemError
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(send): " << ex << endl; dlog->crit() << "(send): " << ex << endl;
msg.swapHead(); msg.swapHead();
return erHardwareError; return erHardwareError;
} }
// Пауза, чтобы не ловить свою посылку // Пауза, чтобы не ловить свою посылку
if( aftersend_msec > 0 ) if( aftersend_msec > 0 )
msleep(aftersend_msec); msleep(aftersend_msec);
return erNoError; return erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusClient::initLog( std::shared_ptr<uniset::Configuration> conf, void ModbusClient::initLog( std::shared_ptr<uniset::Configuration> conf,
const std::string& lname, const string& logfile ) const std::string& lname, const string& logfile )
{ {
conf->initLogStream(dlog, lname); conf->initLogStream(dlog, lname);
if( !logfile.empty() ) if( !logfile.empty() )
dlog->logFile( logfile ); dlog->logFile( logfile );
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusClient::setLog( std::shared_ptr<DebugStream> l ) void ModbusClient::setLog( std::shared_ptr<DebugStream> l )
{ {
this->dlog = l; this->dlog = l;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusClient::printProcessingTime() void ModbusClient::printProcessingTime()
{ {
if( dlog->is_info() ) if( dlog->is_info() )
{ {
dlog->info() << "(processingTime): " dlog->info() << "(processingTime): "
<< tmProcessing.getCurrent() << " [мсек]" << endl; << tmProcessing.getCurrent() << " [мсек]" << endl;
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -21,146 +21,146 @@ ...@@ -21,146 +21,146 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace uniset; using namespace uniset;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
static ComPort::Speed checkSpeed[] = static ComPort::Speed checkSpeed[] =
{ {
ComPort::ComSpeed9600, ComPort::ComSpeed9600,
ComPort::ComSpeed19200, ComPort::ComSpeed19200,
ComPort::ComSpeed38400, ComPort::ComSpeed38400,
ComPort::ComSpeed57600, ComPort::ComSpeed57600,
ComPort::ComSpeed4800, ComPort::ComSpeed4800,
ComPort::ComSpeed115200, ComPort::ComSpeed115200,
ComPort::ComSpeed0 ComPort::ComSpeed0
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusAddr ModbusHelpers::autodetectSlave( ModbusClient* m, ModbusAddr ModbusHelpers::autodetectSlave( ModbusClient* m,
ModbusAddr beg, ModbusAddr end, ModbusAddr beg, ModbusAddr end,
ModbusData reg, ModbusData reg,
SlaveFunctionCode fn ) SlaveFunctionCode fn )
{ {
if( beg > end ) if( beg > end )
{ {
ModbusAddr tmp = beg; ModbusAddr tmp = beg;
beg = end; beg = end;
end = tmp; end = tmp;
} }
for( ModbusAddr a = beg; a <= end; a++ ) for( ModbusAddr a = beg; a <= end; a++ )
{ {
try try
{ {
if( fn == fnReadInputRegisters ) if( fn == fnReadInputRegisters )
{ {
m->read04(a, reg, 1); m->read04(a, reg, 1);
} }
else if( fn == fnReadInputStatus ) else if( fn == fnReadInputStatus )
{ {
m->read02(a, reg, 1); m->read02(a, reg, 1);
} }
else if( fn == fnReadCoilStatus ) else if( fn == fnReadCoilStatus )
{ {
m->read01(a, reg, 1); m->read01(a, reg, 1);
} }
else if( fn == fnReadOutputRegisters ) else if( fn == fnReadOutputRegisters )
{ {
m->read03(a, reg, 1); m->read03(a, reg, 1);
} }
else else
throw mbException(erOperationFailed); throw mbException(erOperationFailed);
return a; return a;
} }
catch( ModbusRTU::mbException& ex ) catch( ModbusRTU::mbException& ex )
{ {
if( ex.err < erInternalErrorCode ) if( ex.err < erInternalErrorCode )
return a; // узел ответил ошибкой (но связь то есть) return a; // узел ответил ошибкой (но связь то есть)
} }
catch(...) {} catch(...) {}
if( (beg == 0xff) || (end == 0xff) ) if( (beg == 0xff) || (end == 0xff) )
break; break;
} }
throw TimeOut(); throw TimeOut();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusAddr ModbusHelpers::autodetectSlave( std::string dev, ComPort::Speed s, int tout, ModbusAddr ModbusHelpers::autodetectSlave( std::string dev, ComPort::Speed s, int tout,
ModbusAddr beg, ModbusAddr end, ModbusAddr beg, ModbusAddr end,
ModbusData reg, ModbusData reg,
SlaveFunctionCode fn ) SlaveFunctionCode fn )
{ {
ModbusRTUMaster mb(dev); ModbusRTUMaster mb(dev);
mb.setSpeed(s); mb.setSpeed(s);
mb.setTimeout(tout); mb.setTimeout(tout);
return autodetectSlave( &mb, beg, end, reg, fn ); return autodetectSlave( &mb, beg, end, reg, fn );
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ComPort::Speed ModbusHelpers::autodetectSpeed( ModbusRTUMaster* m, ModbusAddr slave, ComPort::Speed ModbusHelpers::autodetectSpeed( ModbusRTUMaster* m, ModbusAddr slave,
ModbusData reg, SlaveFunctionCode fn ) ModbusData reg, SlaveFunctionCode fn )
{ {
ComPort::Speed cur = m->getSpeed(); ComPort::Speed cur = m->getSpeed();
ComPort::Speed s = ComPort::ComSpeed0; ComPort::Speed s = ComPort::ComSpeed0;
for( unsigned int i = 0; checkSpeed[i] != ComPort::ComSpeed0; i++ ) for( unsigned int i = 0; checkSpeed[i] != ComPort::ComSpeed0; i++ )
{ {
try try
{ {
m->setSpeed( checkSpeed[i] ); m->setSpeed( checkSpeed[i] );
if( fn == fnReadInputRegisters ) if( fn == fnReadInputRegisters )
{ {
m->read04(slave, reg, 1); m->read04(slave, reg, 1);
} }
else if( fn == fnReadInputStatus ) else if( fn == fnReadInputStatus )
{ {
m->read02(slave, reg, 1); m->read02(slave, reg, 1);
} }
else if( fn == fnReadCoilStatus ) else if( fn == fnReadCoilStatus )
{ {
m->read01(slave, reg, 1); m->read01(slave, reg, 1);
} }
else if( fn == fnReadOutputRegisters ) else if( fn == fnReadOutputRegisters )
{ {
m->read03(slave, reg, 1); m->read03(slave, reg, 1);
} }
else else
throw mbException(erOperationFailed); throw mbException(erOperationFailed);
s = checkSpeed[i]; s = checkSpeed[i];
break; break;
} }
catch( ModbusRTU::mbException& ex ) catch( ModbusRTU::mbException& ex )
{ {
if( ex.err < erInternalErrorCode ) if( ex.err < erInternalErrorCode )
{ {
s = checkSpeed[i]; s = checkSpeed[i];
break; // узел ответил ошибкой (но связь то есть) break; // узел ответил ошибкой (но связь то есть)
} }
} }
catch(...) {} catch(...) {}
} }
m->setSpeed(cur); m->setSpeed(cur);
if( s != ComPort::ComSpeed0 ) if( s != ComPort::ComSpeed0 )
return s; return s;
throw TimeOut(); throw TimeOut();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ComPort::Speed ModbusHelpers::autodetectSpeed( std::string dev, ModbusRTU::ModbusAddr slave, int tout, ComPort::Speed ModbusHelpers::autodetectSpeed( std::string dev, ModbusRTU::ModbusAddr slave, int tout,
ModbusData reg, SlaveFunctionCode fn ) ModbusData reg, SlaveFunctionCode fn )
{ {
ModbusRTUMaster mb(dev); ModbusRTUMaster mb(dev);
mb.setTimeout(tout); mb.setTimeout(tout);
return autodetectSpeed( &mb, slave, reg, fn ); return autodetectSpeed( &mb, slave, reg, fn );
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -24,113 +24,113 @@ ...@@ -24,113 +24,113 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace uniset; using namespace uniset;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUMaster::ModbusRTUMaster( const string& dev, bool use485, bool tr_ctl ): ModbusRTUMaster::ModbusRTUMaster( const string& dev, bool use485, bool tr_ctl ):
port(NULL), port(NULL),
myport(true) myport(true)
{ {
if( use485 ) if( use485 )
{ {
#ifndef DISABLE_COMPORT_485F #ifndef DISABLE_COMPORT_485F
ComPort485F* cp; ComPort485F* cp;
if( dev == "/dev/ttyS2" ) if( dev == "/dev/ttyS2" )
cp = new ComPort485F(dev, 5, tr_ctl); cp = new ComPort485F(dev, 5, tr_ctl);
else if( dev == "/dev/ttyS3" ) else if( dev == "/dev/ttyS3" )
cp = new ComPort485F(dev, 6, tr_ctl); cp = new ComPort485F(dev, 6, tr_ctl);
else else
throw Exception("Open ComPort FAILED! dev must be /dev/ttyS2 or /dev/tytS3"); throw Exception("Open ComPort FAILED! dev must be /dev/ttyS2 or /dev/tytS3");
port = cp; port = cp;
#else #else
throw Exception("Open ComPort485F FAILED! DISABLE_COMPORT_485F"); throw Exception("Open ComPort485F FAILED! DISABLE_COMPORT_485F");
#endif // #ifndef DISABLE_COMPORT_485F #endif // #ifndef DISABLE_COMPORT_485F
} }
else else
port = new ComPort(dev); port = new ComPort(dev);
port->setSpeed(ComPort::ComSpeed38400); port->setSpeed(ComPort::ComSpeed38400);
port->setParity(ComPort::NoParity); port->setParity(ComPort::NoParity);
port->setCharacterSize(ComPort::CSize8); port->setCharacterSize(ComPort::CSize8);
port->setStopBits(ComPort::OneBit); port->setStopBits(ComPort::OneBit);
port->setWaiting(true); port->setWaiting(true);
port->setTimeout(replyTimeOut_ms); port->setTimeout(replyTimeOut_ms);
// port->setBlocking(false); // port->setBlocking(false);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUMaster::ModbusRTUMaster( ComPort* com ): ModbusRTUMaster::ModbusRTUMaster( ComPort* com ):
port(com), port(com),
myport(false) myport(false)
{ {
if( !port ) if( !port )
throw Exception("comport=NULL!!"); throw Exception("comport=NULL!!");
port->setSpeed(ComPort::ComSpeed38400); port->setSpeed(ComPort::ComSpeed38400);
port->setParity(ComPort::NoParity); port->setParity(ComPort::NoParity);
port->setCharacterSize(ComPort::CSize8); port->setCharacterSize(ComPort::CSize8);
port->setStopBits(ComPort::OneBit); port->setStopBits(ComPort::OneBit);
port->setWaiting(true); port->setWaiting(true);
port->setTimeout(replyTimeOut_ms); port->setTimeout(replyTimeOut_ms);
// port->setBlocking(false); // port->setBlocking(false);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUMaster::~ModbusRTUMaster() ModbusRTUMaster::~ModbusRTUMaster()
{ {
if( myport ) if( myport )
delete port; delete port;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUMaster::cleanupChannel() void ModbusRTUMaster::cleanupChannel()
{ {
if( port ) if( port )
port->cleanupChannel(); port->cleanupChannel();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUMaster::setSpeed( ComPort::Speed s ) void ModbusRTUMaster::setSpeed( ComPort::Speed s )
{ {
if( port != NULL ) if( port != NULL )
port->setSpeed(s); port->setSpeed(s);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
void ModbusRTUMaster::setSpeed( const std::string& s ) void ModbusRTUMaster::setSpeed( const std::string& s )
{ {
if( port != NULL ) if( port != NULL )
port->setSpeed(s); port->setSpeed(s);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ComPort::Speed ModbusRTUMaster::getSpeed() ComPort::Speed ModbusRTUMaster::getSpeed()
{ {
if( port == NULL ) if( port == NULL )
return ComPort::ComSpeed0; return ComPort::ComSpeed0;
return port->getSpeed(); return port->getSpeed();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ComPort::Parity ModbusRTUMaster::getParity() ComPort::Parity ModbusRTUMaster::getParity()
{ {
if( port != NULL) if( port != NULL)
port->getParity(); port->getParity();
return ComPort::NoParity; return ComPort::NoParity;
} }
// -------------------------------------------------------------------------
void ModbusRTUMaster::setParity( ComPort::Parity parity )
{
if( port != NULL)
port->setParity(parity);
}
// -------------------------------------------------------------------------
void ModbusRTUMaster::setCharacterSize( ComPort::CharacterSize csize )
{
if( port != NULL)
port->setCharacterSize(csize);
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUMaster::setParity( ComPort::Parity parity )
{
if( port != NULL)
port->setParity(parity);
}
// -------------------------------------------------------------------------
void ModbusRTUMaster::setCharacterSize( ComPort::CharacterSize csize )
{
if( port != NULL)
port->setCharacterSize(csize);
}
// -------------------------------------------------------------------------
ComPort::CharacterSize ModbusRTUMaster::getCharacterSize() ComPort::CharacterSize ModbusRTUMaster::getCharacterSize()
{ {
if( port != NULL) if( port != NULL)
...@@ -147,56 +147,56 @@ namespace uniset ...@@ -147,56 +147,56 @@ namespace uniset
return ComPort::OneBit; return ComPort::OneBit;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUMaster::setStopBits( ComPort::StopBits sBit ) void ModbusRTUMaster::setStopBits( ComPort::StopBits sBit )
{ {
if( port != NULL) if( port != NULL)
port->setStopBits(sBit); port->setStopBits(sBit);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
timeout_t ModbusRTUMaster::getTimeout() const timeout_t ModbusRTUMaster::getTimeout() const
{ {
if( port == NULL ) if( port == NULL )
return 0; return 0;
return port->getTimeout(); return port->getTimeout();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusRTUMaster::getNextData( unsigned char* buf, size_t len ) size_t ModbusRTUMaster::getNextData( unsigned char* buf, size_t len )
{ {
// if( !port ) return 0; // if( !port ) return 0;
return port->receiveBlock(buf, len); return port->receiveBlock(buf, len);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
void ModbusRTUMaster::setChannelTimeout( timeout_t msec ) void ModbusRTUMaster::setChannelTimeout( timeout_t msec )
{ {
if( port ) if( port )
port->setTimeout(msec); port->setTimeout(msec);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
mbErrCode ModbusRTUMaster::sendData(unsigned char* buf, size_t len ) mbErrCode ModbusRTUMaster::sendData(unsigned char* buf, size_t len )
{ {
try try
{ {
port->sendBlock(buf, len); port->sendBlock(buf, len);
} }
catch( const uniset::Exception& ex ) // SystemError catch( const uniset::Exception& ex ) // SystemError
{ {
dlog->crit() << "(send): " << ex << endl; dlog->crit() << "(send): " << ex << endl;
return erHardwareError; return erHardwareError;
} }
return erNoError; return erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUMaster::query( ModbusAddr addr, ModbusMessage& msg, mbErrCode ModbusRTUMaster::query( ModbusAddr addr, ModbusMessage& msg,
ModbusMessage& reply, timeout_t timeout ) ModbusMessage& reply, timeout_t timeout )
{ {
mbErrCode res = send(msg); mbErrCode res = send(msg);
if( res != erNoError ) if( res != erNoError )
return res; return res;
return recv(addr, msg.pduhead.func, reply, timeout); return recv(addr, msg.pduhead.func, reply, timeout);
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -25,199 +25,199 @@ ...@@ -25,199 +25,199 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace uniset; using namespace uniset;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUSlave::ModbusRTUSlave( const string& dev, bool use485, bool tr_ctl ): ModbusRTUSlave::ModbusRTUSlave( const string& dev, bool use485, bool tr_ctl ):
port(NULL), port(NULL),
myport(true) myport(true)
{ {
if( use485 ) if( use485 )
{ {
#ifndef DISABLE_COMPORT_485F #ifndef DISABLE_COMPORT_485F
ComPort485F* cp; ComPort485F* cp;
if( dev == "/dev/ttyS2" ) if( dev == "/dev/ttyS2" )
cp = new ComPort485F(dev, 5, tr_ctl); cp = new ComPort485F(dev, 5, tr_ctl);
else if( dev == "/dev/ttyS3" ) else if( dev == "/dev/ttyS3" )
cp = new ComPort485F(dev, 6, tr_ctl); cp = new ComPort485F(dev, 6, tr_ctl);
else else
throw Exception("Open ComPort FAILED! dev must be /dev/ttyS2 or /dev/tytS3"); throw Exception("Open ComPort FAILED! dev must be /dev/ttyS2 or /dev/tytS3");
port = cp; port = cp;
#else #else
throw Exception("Open ComPort485F FAILED! DISABLE_COMPORT_485F"); throw Exception("Open ComPort485F FAILED! DISABLE_COMPORT_485F");
#endif // #ifndef DISABLE_COMPORT_485F #endif // #ifndef DISABLE_COMPORT_485F
} }
else else
port = new ComPort(dev); port = new ComPort(dev);
port->setSpeed(ComPort::ComSpeed38400); port->setSpeed(ComPort::ComSpeed38400);
port->setParity(ComPort::NoParity); port->setParity(ComPort::NoParity);
port->setCharacterSize(ComPort::CSize8); port->setCharacterSize(ComPort::CSize8);
port->setStopBits(ComPort::OneBit); port->setStopBits(ComPort::OneBit);
port->setWaiting(true); port->setWaiting(true);
port->setTimeout(recvTimeOut_ms); port->setTimeout(recvTimeOut_ms);
// port->setBlocking(false); // port->setBlocking(false);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUSlave::ModbusRTUSlave( ComPort* com ): ModbusRTUSlave::ModbusRTUSlave( ComPort* com ):
port(com), port(com),
myport(false) myport(false)
{ {
port->setSpeed(ComPort::ComSpeed38400); port->setSpeed(ComPort::ComSpeed38400);
port->setParity(ComPort::NoParity); port->setParity(ComPort::NoParity);
port->setCharacterSize(ComPort::CSize8); port->setCharacterSize(ComPort::CSize8);
port->setStopBits(ComPort::OneBit); port->setStopBits(ComPort::OneBit);
port->setWaiting(true); port->setWaiting(true);
port->setTimeout(recvTimeOut_ms); port->setTimeout(recvTimeOut_ms);
// port->setBlocking(false); // port->setBlocking(false);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUSlave::~ModbusRTUSlave() ModbusRTUSlave::~ModbusRTUSlave()
{ {
if( myport ) if( myport )
delete port; delete port;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
ComPort::Speed ModbusRTUSlave::getSpeed() ComPort::Speed ModbusRTUSlave::getSpeed()
{ {
if( port == NULL ) if( port == NULL )
return ComPort::ComSpeed0; return ComPort::ComSpeed0;
return port->getSpeed(); return port->getSpeed();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUSlave::setCharSize( ComPort::CharacterSize s ) void ModbusRTUSlave::setCharSize( ComPort::CharacterSize s )
{ {
if( port != NULL ) if( port != NULL )
port->setCharacterSize(s); port->setCharacterSize(s);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUSlave::setStopBits( ComPort::StopBits b ) void ModbusRTUSlave::setStopBits( ComPort::StopBits b )
{ {
if( port != NULL ) if( port != NULL )
port->setStopBits(b); port->setStopBits(b);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUSlave::setParity( ComPort::Parity p ) void ModbusRTUSlave::setParity( ComPort::Parity p )
{ {
if( port != NULL ) if( port != NULL )
port->setParity(p); port->setParity(p);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUSlave::setParity( const std::string& p ) void ModbusRTUSlave::setParity( const std::string& p )
{ {
setParity(ComPort::getParity(p)); setParity(ComPort::getParity(p));
} }
// -------------------------------------------------------------------------
void ModbusRTUSlave::setSpeed( ComPort::Speed s )
{
if( port != NULL )
port->setSpeed(s);
}
// --------------------------------------------------------------------------------
void ModbusRTUSlave::setSpeed( const std::string& s )
{
if( port != NULL )
port->setSpeed(s);
}
// --------------------------------------------------------------------------------
size_t ModbusRTUSlave::getNextData( unsigned char* buf, int len )
{
// if( !port ) return 0;
return port->receiveBlock(buf, len);
}
// --------------------------------------------------------------------------------
void ModbusRTUSlave::setChannelTimeout( timeout_t msec )
{
if( msec == UniSetTimer::WaitUpTime )
port->setTimeout(15 * 60 * 1000); // используем просто большое время (15 минут)
else
port->setTimeout(msec);
}
// --------------------------------------------------------------------------------
mbErrCode ModbusRTUSlave::sendData( unsigned char* buf, int len )
{
try
{
port->sendBlock(buf, len);
}
catch( const uniset::Exception& ex ) // SystemError
{
if( dlog->is_crit() )
dlog->crit() << "(send): " << ex << endl;
return erHardwareError;
}
return erNoError;
}
// -------------------------------------------------------------------------
void ModbusRTUSlave::terminate()
{
try
{
}
catch(...) {}
}
// -------------------------------------------------------------------------
bool ModbusRTUSlave::isActive() const
{
return false;
}
// -------------------------------------------------------------------------
mbErrCode ModbusRTUSlave::realReceive(const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t timeout )
{
if( !recvMutex.try_lock_for( std::chrono::milliseconds(timeout)) )
{
if( dlog->is_crit() )
dlog->crit() << "(ModbusRTUSlave::receive): Don`t lock recvMutex.." << endl;
return erTimeOut;
}
std::lock_guard<std::timed_mutex> lk(recvMutex, std::adopt_lock);
ModbusMessage buf;
mbErrCode res = erBadReplyNodeAddress;
do
{
res = recv(vmbaddr, buf, timeout);
if( res != erNoError && res != erBadReplyNodeAddress )
{
// Если ошибка подразумевает посылку ответа с сообщением об ошибке
// то посылаем
if( res < erInternalErrorCode )
{
ErrorRetMessage em( buf.addr(), buf.func(), res );
buf = em.transport_msg();
send(buf);
printProcessingTime();
}
if( aftersend_msec > 0 )
msleep(aftersend_msec);
return res;
}
// если полученный пакет адресован
// не данному узлу (и не широковещательный)
// то ждать следующий...
}
while( res == erBadReplyNodeAddress );
return processing(buf);
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUSlave::setSpeed( ComPort::Speed s )
{
if( port != NULL )
port->setSpeed(s);
}
// --------------------------------------------------------------------------------
void ModbusRTUSlave::setSpeed( const std::string& s )
{
if( port != NULL )
port->setSpeed(s);
}
// --------------------------------------------------------------------------------
size_t ModbusRTUSlave::getNextData( unsigned char* buf, int len )
{
// if( !port ) return 0;
return port->receiveBlock(buf, len);
}
// --------------------------------------------------------------------------------
void ModbusRTUSlave::setChannelTimeout( timeout_t msec )
{
if( msec == UniSetTimer::WaitUpTime )
port->setTimeout(15 * 60 * 1000); // используем просто большое время (15 минут)
else
port->setTimeout(msec);
}
// --------------------------------------------------------------------------------
mbErrCode ModbusRTUSlave::sendData( unsigned char* buf, int len )
{
try
{
port->sendBlock(buf, len);
}
catch( const uniset::Exception& ex ) // SystemError
{
if( dlog->is_crit() )
dlog->crit() << "(send): " << ex << endl;
return erHardwareError;
}
return erNoError;
}
// -------------------------------------------------------------------------
void ModbusRTUSlave::terminate()
{
try
{
}
catch(...) {}
}
// -------------------------------------------------------------------------
bool ModbusRTUSlave::isActive() const
{
return false;
}
// -------------------------------------------------------------------------
mbErrCode ModbusRTUSlave::realReceive(const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t timeout )
{
if( !recvMutex.try_lock_for( std::chrono::milliseconds(timeout)) )
{
if( dlog->is_crit() )
dlog->crit() << "(ModbusRTUSlave::receive): Don`t lock recvMutex.." << endl;
return erTimeOut;
}
std::lock_guard<std::timed_mutex> lk(recvMutex, std::adopt_lock);
ModbusMessage buf;
mbErrCode res = erBadReplyNodeAddress;
do
{
res = recv(vmbaddr, buf, timeout);
if( res != erNoError && res != erBadReplyNodeAddress )
{
// Если ошибка подразумевает посылку ответа с сообщением об ошибке
// то посылаем
if( res < erInternalErrorCode )
{
ErrorRetMessage em( buf.addr(), buf.func(), res );
buf = em.transport_msg();
send(buf);
printProcessingTime();
}
if( aftersend_msec > 0 )
msleep(aftersend_msec);
return res;
}
// если полученный пакет адресован
// не данному узлу (и не широковещательный)
// то ждать следующий...
}
while( res == erBadReplyNodeAddress );
return processing(buf);
}
// -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -18,174 +18,174 @@ ...@@ -18,174 +18,174 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace std; using namespace std;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUSlaveSlot::ModbusRTUSlaveSlot( const std::string& dev, bool use485, bool tr_ctl ): ModbusRTUSlaveSlot::ModbusRTUSlaveSlot( const std::string& dev, bool use485, bool tr_ctl ):
ModbusRTUSlave(dev, use485, tr_ctl) ModbusRTUSlave(dev, use485, tr_ctl)
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUSlaveSlot::ModbusRTUSlaveSlot( ComPort* c ): ModbusRTUSlaveSlot::ModbusRTUSlaveSlot( ComPort* c ):
ModbusRTUSlave(c) ModbusRTUSlave(c)
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTUSlaveSlot::~ModbusRTUSlaveSlot() ModbusRTUSlaveSlot::~ModbusRTUSlaveSlot()
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::readCoilStatus( ReadCoilMessage& query, mbErrCode ModbusRTUSlaveSlot::readCoilStatus( ReadCoilMessage& query,
ReadCoilRetMessage& reply ) ReadCoilRetMessage& reply )
{ {
if( !slReadCoil ) if( !slReadCoil )
return erOperationFailed; return erOperationFailed;
return slReadCoil(query, reply); return slReadCoil(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::readInputStatus( ReadInputStatusMessage& query, mbErrCode ModbusRTUSlaveSlot::readInputStatus( ReadInputStatusMessage& query,
ReadInputStatusRetMessage& reply ) ReadInputStatusRetMessage& reply )
{ {
if( !slReadInputStatus ) if( !slReadInputStatus )
return erOperationFailed; return erOperationFailed;
return slReadInputStatus(query, reply); return slReadInputStatus(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::readOutputRegisters( ReadOutputMessage& query, mbErrCode ModbusRTUSlaveSlot::readOutputRegisters( ReadOutputMessage& query,
ReadOutputRetMessage& reply ) ReadOutputRetMessage& reply )
{ {
if( !slReadOutputs ) if( !slReadOutputs )
return erOperationFailed; return erOperationFailed;
return slReadOutputs(query, reply); return slReadOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::readInputRegisters( ReadInputMessage& query, mbErrCode ModbusRTUSlaveSlot::readInputRegisters( ReadInputMessage& query,
ReadInputRetMessage& reply ) ReadInputRetMessage& reply )
{ {
if( !slReadInputs ) if( !slReadInputs )
return erOperationFailed; return erOperationFailed;
return slReadInputs(query, reply); return slReadInputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::forceMultipleCoils( ForceCoilsMessage& query, mbErrCode ModbusRTUSlaveSlot::forceMultipleCoils( ForceCoilsMessage& query,
ForceCoilsRetMessage& reply ) ForceCoilsRetMessage& reply )
{ {
if( !slForceCoils ) if( !slForceCoils )
return erOperationFailed; return erOperationFailed;
return slForceCoils(query, reply); return slForceCoils(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::writeOutputRegisters( WriteOutputMessage& query, mbErrCode ModbusRTUSlaveSlot::writeOutputRegisters( WriteOutputMessage& query,
WriteOutputRetMessage& reply ) WriteOutputRetMessage& reply )
{ {
if( !slWriteOutputs ) if( !slWriteOutputs )
return erOperationFailed; return erOperationFailed;
return slWriteOutputs(query, reply); return slWriteOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::diagnostics( DiagnosticMessage& query, mbErrCode ModbusRTUSlaveSlot::diagnostics( DiagnosticMessage& query,
DiagnosticRetMessage& reply ) DiagnosticRetMessage& reply )
{ {
if( !slDiagnostics ) if( !slDiagnostics )
return erOperationFailed; return erOperationFailed;
return slDiagnostics(query, reply); return slDiagnostics(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusRTUSlaveSlot::read4314( ModbusRTU::MEIMessageRDI& query, ModbusRTU::mbErrCode ModbusRTUSlaveSlot::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply ) ModbusRTU::MEIMessageRetRDI& reply )
{ {
if( !slMEIRDI ) if( !slMEIRDI )
return erOperationFailed; return erOperationFailed;
return slMEIRDI(query, reply); return slMEIRDI(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::forceSingleCoil( ForceSingleCoilMessage& query, mbErrCode ModbusRTUSlaveSlot::forceSingleCoil( ForceSingleCoilMessage& query,
ForceSingleCoilRetMessage& reply ) ForceSingleCoilRetMessage& reply )
{ {
if( !slForceSingleCoil ) if( !slForceSingleCoil )
return erOperationFailed; return erOperationFailed;
return slForceSingleCoil(query, reply); return slForceSingleCoil(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::writeOutputSingleRegister( WriteSingleOutputMessage& query, mbErrCode ModbusRTUSlaveSlot::writeOutputSingleRegister( WriteSingleOutputMessage& query,
WriteSingleOutputRetMessage& reply ) WriteSingleOutputRetMessage& reply )
{ {
if( !slWriteSingleOutputs ) if( !slWriteSingleOutputs )
return erOperationFailed; return erOperationFailed;
return slWriteSingleOutputs(query, reply); return slWriteSingleOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusRTUSlaveSlot::journalCommand( JournalCommandMessage& query, mbErrCode ModbusRTUSlaveSlot::journalCommand( JournalCommandMessage& query,
JournalCommandRetMessage& reply ) JournalCommandRetMessage& reply )
{ {
if( !slJournalCommand ) if( !slJournalCommand )
return erOperationFailed; return erOperationFailed;
return slJournalCommand(query, reply); return slJournalCommand(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusRTUSlaveSlot::setDateTime( ModbusRTU::SetDateTimeMessage& query, ModbusRTU::mbErrCode ModbusRTUSlaveSlot::setDateTime( ModbusRTU::SetDateTimeMessage& query,
ModbusRTU::SetDateTimeRetMessage& reply ) ModbusRTU::SetDateTimeRetMessage& reply )
{ {
if( !slSetDateTime ) if( !slSetDateTime )
return erOperationFailed; return erOperationFailed;
return slSetDateTime(query, reply); return slSetDateTime(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusRTUSlaveSlot::remoteService( ModbusRTU::RemoteServiceMessage& query, ModbusRTU::mbErrCode ModbusRTUSlaveSlot::remoteService( ModbusRTU::RemoteServiceMessage& query,
ModbusRTU::RemoteServiceRetMessage& reply ) ModbusRTU::RemoteServiceRetMessage& reply )
{ {
if( !slRemoteService ) if( !slRemoteService )
return erOperationFailed; return erOperationFailed;
return slRemoteService(query, reply); return slRemoteService(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusRTUSlaveSlot::fileTransfer( ModbusRTU::FileTransferMessage& query, ModbusRTU::mbErrCode ModbusRTUSlaveSlot::fileTransfer( ModbusRTU::FileTransferMessage& query,
ModbusRTU::FileTransferRetMessage& reply ) ModbusRTU::FileTransferRetMessage& reply )
{ {
if( !slFileTransfer ) if( !slFileTransfer )
return erOperationFailed; return erOperationFailed;
return slFileTransfer(query, reply); return slFileTransfer(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusRTUSlaveSlot::terminate() void ModbusRTUSlaveSlot::terminate()
{ {
try try
{ {
ModbusRTUSlave::terminate(); ModbusRTUSlave::terminate();
} }
catch(...) {} catch(...) {}
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ComPort* ModbusRTUSlaveSlot::getComPort() ComPort* ModbusRTUSlaveSlot::getComPort()
{ {
return port; return port;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -18,92 +18,92 @@ ...@@ -18,92 +18,92 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace std; using namespace std;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusServerSlot::ModbusServerSlot() ModbusServerSlot::ModbusServerSlot()
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusServerSlot::~ModbusServerSlot() ModbusServerSlot::~ModbusServerSlot()
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectReadCoil( ReadCoilSlot sl ) void ModbusServerSlot::connectReadCoil( ReadCoilSlot sl )
{ {
slReadCoil = sl; slReadCoil = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectReadInputStatus( ReadInputStatusSlot sl ) void ModbusServerSlot::connectReadInputStatus( ReadInputStatusSlot sl )
{ {
slReadInputStatus = sl; slReadInputStatus = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectReadOutput( ReadOutputSlot sl ) void ModbusServerSlot::connectReadOutput( ReadOutputSlot sl )
{ {
slReadOutputs = sl; slReadOutputs = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectReadInput( ReadInputSlot sl ) void ModbusServerSlot::connectReadInput( ReadInputSlot sl )
{ {
slReadInputs = sl; slReadInputs = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectForceCoils( ForceCoilsSlot sl ) void ModbusServerSlot::connectForceCoils( ForceCoilsSlot sl )
{ {
slForceCoils = sl; slForceCoils = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectWriteOutput( WriteOutputSlot sl ) void ModbusServerSlot::connectWriteOutput( WriteOutputSlot sl )
{ {
slWriteOutputs = sl; slWriteOutputs = sl;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void ModbusServerSlot::connectWriteSingleOutput( WriteSingleOutputSlot sl ) void ModbusServerSlot::connectWriteSingleOutput( WriteSingleOutputSlot sl )
{ {
slWriteSingleOutputs = sl; slWriteSingleOutputs = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectDiagnostics( DiagnosticsSlot sl ) void ModbusServerSlot::connectDiagnostics( DiagnosticsSlot sl )
{ {
slDiagnostics = sl; slDiagnostics = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectMEIRDI( MEIRDISlot sl ) void ModbusServerSlot::connectMEIRDI( MEIRDISlot sl )
{ {
slMEIRDI = sl; slMEIRDI = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectForceSingleCoil( ForceSingleCoilSlot sl ) void ModbusServerSlot::connectForceSingleCoil( ForceSingleCoilSlot sl )
{ {
slForceSingleCoil = sl; slForceSingleCoil = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectJournalCommand( JournalCommandSlot sl ) void ModbusServerSlot::connectJournalCommand( JournalCommandSlot sl )
{ {
slJournalCommand = sl; slJournalCommand = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectSetDateTime( SetDateTimeSlot sl ) void ModbusServerSlot::connectSetDateTime( SetDateTimeSlot sl )
{ {
slSetDateTime = sl; slSetDateTime = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectRemoteService( RemoteServiceSlot sl ) void ModbusServerSlot::connectRemoteService( RemoteServiceSlot sl )
{ {
slRemoteService = sl; slRemoteService = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusServerSlot::connectFileTransfer( FileTransferSlot sl ) void ModbusServerSlot::connectFileTransfer( FileTransferSlot sl )
{ {
slFileTransfer = sl; slFileTransfer = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -20,257 +20,257 @@ ...@@ -20,257 +20,257 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
#define USE_BUFFER_FOR_READ 1 #define USE_BUFFER_FOR_READ 1
#define DEFAULT_BUFFER_SIZE_FOR_READ 255 #define DEFAULT_BUFFER_SIZE_FOR_READ 255
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusTCPCore::readNextData(UTCPStream* tcp, size_t ModbusTCPCore::readNextData(UTCPStream* tcp,
std::queue<unsigned char>& qrecv, size_t max ) std::queue<unsigned char>& qrecv, size_t max )
{ {
if( !tcp ) // || !tcp->available() ) if( !tcp ) // || !tcp->available() )
return 0; return 0;
size_t i = 0; size_t i = 0;
bool commfail = false; bool commfail = false;
#ifdef USE_BUFFER_FOR_READ #ifdef USE_BUFFER_FOR_READ
max = std::max(max, (size_t)DEFAULT_BUFFER_SIZE_FOR_READ); max = std::max(max, (size_t)DEFAULT_BUFFER_SIZE_FOR_READ);
char* buf = new char[max]; char* buf = new char[max];
try try
{ {
ssize_t l = tcp->receiveBytes(buf, max); ssize_t l = tcp->receiveBytes(buf, max);
if( l > 0 ) if( l > 0 )
{ {
for( ssize_t k = 0; k < l; k++ ) for( ssize_t k = 0; k < l; k++ )
qrecv.push(buf[k]); qrecv.push(buf[k]);
i = l; i = l;
} }
// канал закрыт! // канал закрыт!
if( l == 0 ) if( l == 0 )
commfail = true; commfail = true;
} }
catch( Poco::TimeoutException& ex ) catch( Poco::TimeoutException& ex )
{ {
} }
catch( Poco::Net::NetException& e ) catch( Poco::Net::NetException& e )
{ {
commfail = true; commfail = true;
} }
delete [] buf; delete [] buf;
#else #else
try try
{ {
for( ; i < max; i++ ) for( ; i < max; i++ )
{ {
// (не оптимально): читаем один символ за раз.. // (не оптимально): читаем один символ за раз..
unsigned char c; unsigned char c;
ssize_t l = tcp->readData(&c, sizeof(c), 0, t); ssize_t l = tcp->readData(&c, sizeof(c), 0, t);
if( l == 0 ) if( l == 0 )
{ {
commfail = true; commfail = true;
break; break;
} }
if( l < 0 ) if( l < 0 )
break; break;
qrecv.push(c); qrecv.push(c);
} }
} }
catch( ost::SockException& e ) catch( ost::SockException& e )
{ {
} }
#endif #endif
if( commfail ) if( commfail )
throw uniset::CommFailed(); throw uniset::CommFailed();
return i; return i;
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
size_t ModbusTCPCore::getNextData(UTCPStream* tcp, size_t ModbusTCPCore::getNextData(UTCPStream* tcp,
std::queue<unsigned char>& qrecv, std::queue<unsigned char>& qrecv,
unsigned char* buf, size_t len) unsigned char* buf, size_t len)
{ {
if( qrecv.empty() || qrecv.size() < len ) if( qrecv.empty() || qrecv.size() < len )
{ {
if( !tcp ) // || !tcp->available() ) if( !tcp ) // || !tcp->available() )
return 0; return 0;
if( len <= 0 ) if( len <= 0 )
len = 7; len = 7;
try try
{ {
size_t ret = ModbusTCPCore::readNextData(tcp, qrecv, len); size_t ret = ModbusTCPCore::readNextData(tcp, qrecv, len);
if( ret == 0 ) if( ret == 0 )
return 0; return 0;
} }
catch( uniset::CommFailed& ex ) catch( uniset::CommFailed& ex )
{ {
if( qrecv.empty() ) if( qrecv.empty() )
return 0; return 0;
} }
} }
size_t i = 0; size_t i = 0;
for( ; i < len && !qrecv.empty(); i++ ) for( ; i < len && !qrecv.empty(); i++ )
{ {
buf[i] = qrecv.front(); buf[i] = qrecv.front();
qrecv.pop(); qrecv.pop();
} }
return i; return i;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusTCPCore::readDataFD( int fd, std::queue<unsigned char>& qrecv, size_t max , size_t attempts ) size_t ModbusTCPCore::readDataFD( int fd, std::queue<unsigned char>& qrecv, size_t max, size_t attempts )
{ {
bool commfail = false; bool commfail = false;
#ifdef USE_BUFFER_FOR_READ #ifdef USE_BUFFER_FOR_READ
max = std::max(max, (size_t)DEFAULT_BUFFER_SIZE_FOR_READ); max = std::max(max, (size_t)DEFAULT_BUFFER_SIZE_FOR_READ);
char* buf = new char[max]; char* buf = new char[max];
ssize_t l = 0; ssize_t l = 0;
size_t cnt = 0; size_t cnt = 0;
for( size_t a = 0; a < attempts; a++ ) for( size_t a = 0; a < attempts; a++ )
{ {
l = ::read(fd, buf, max); l = ::read(fd, buf, max);
if( l > 0 ) if( l > 0 )
{ {
for( int k = 0; k < l; k++ ) for( int k = 0; k < l; k++ )
qrecv.push(buf[k]); qrecv.push(buf[k]);
cnt += l; cnt += l;
if( cnt >= max ) if( cnt >= max )
break; break;
} }
// канал закрыт! // канал закрыт!
if( l == 0 ) if( l == 0 )
commfail = true; commfail = true;
} }
delete [] buf; delete [] buf;
#else #else
size_t i = 0; size_t i = 0;
for( size_t a = 0; a < attempts; a++ ) for( size_t a = 0; a < attempts; a++ )
{ {
for( ; i < max; i++ ) for( ; i < max; i++ )
{ {
// (не оптимально): читаем один символ за раз.. // (не оптимально): читаем один символ за раз..
unsigned char c; unsigned char c;
ssize_t l = ::read(fd, &c, sizeof(c)); ssize_t l = ::read(fd, &c, sizeof(c));
if( l == 0 ) if( l == 0 )
{ {
commfail = true; commfail = true;
break; break;
} }
if( l < 0 ) if( l < 0 )
break; break;
qrecv.push(c); qrecv.push(c);
} }
} }
#endif #endif
if( commfail ) if( commfail )
throw uniset::CommFailed(); throw uniset::CommFailed();
return std::min(qrecv.size(), max); return std::min(qrecv.size(), max);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
size_t ModbusTCPCore::getDataFD( int fd, std::queue<unsigned char>& qrecv, size_t ModbusTCPCore::getDataFD( int fd, std::queue<unsigned char>& qrecv,
unsigned char* buf, size_t len, size_t attempts ) unsigned char* buf, size_t len, size_t attempts )
{ {
if( qrecv.empty() || qrecv.size() < len ) if( qrecv.empty() || qrecv.size() < len )
{ {
if( len == 0 ) if( len == 0 )
len = 7; len = 7;
try try
{ {
size_t ret = ModbusTCPCore::readDataFD(fd, qrecv, len, attempts); size_t ret = ModbusTCPCore::readDataFD(fd, qrecv, len, attempts);
if( ret == 0 && qrecv.empty() ) if( ret == 0 && qrecv.empty() )
return 0; return 0;
} }
catch( uniset::CommFailed& ex ) catch( uniset::CommFailed& ex )
{ {
if( qrecv.empty() ) if( qrecv.empty() )
return 0; return 0;
} }
} }
size_t i = 0; size_t i = 0;
for( ; i < len && !qrecv.empty(); i++ ) for( ; i < len && !qrecv.empty(); i++ )
{ {
buf[i] = qrecv.front(); buf[i] = qrecv.front();
qrecv.pop(); qrecv.pop();
} }
return i; return i;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPCore::sendData(UTCPStream* tcp, unsigned char* buf, size_t len ) mbErrCode ModbusTCPCore::sendData(UTCPStream* tcp, unsigned char* buf, size_t len )
{ {
if( !tcp ) // || !tcp->available() ) if( !tcp ) // || !tcp->available() )
return erTimeOut; return erTimeOut;
try try
{ {
ssize_t l = tcp->sendBytes(buf, len); ssize_t l = tcp->sendBytes(buf, len);
if( l == len ) if( l == len )
return erNoError; return erNoError;
} }
catch( Poco::Net::NetException& e ) catch( Poco::Net::NetException& e )
{ {
// cerr << "(send): " << e.getString() << ": " << e.getSystemErrorString() << endl; // cerr << "(send): " << e.getString() << ": " << e.getSystemErrorString() << endl;
} }
catch(...) catch(...)
{ {
// cerr << "(send): cath..." << endl; // cerr << "(send): cath..." << endl;
} }
return erHardwareError; return erHardwareError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPCore::sendDataFD( int fd, unsigned char* buf, size_t len ) mbErrCode ModbusTCPCore::sendDataFD( int fd, unsigned char* buf, size_t len )
{ {
ssize_t l = ::write(fd, buf, len); ssize_t l = ::write(fd, buf, len);
if( l == len ) if( l == len )
return erNoError; return erNoError;
return erHardwareError; return erHardwareError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -25,503 +25,503 @@ ...@@ -25,503 +25,503 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace uniset; using namespace uniset;
using namespace Poco; using namespace Poco;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPMaster::ModbusTCPMaster(): ModbusTCPMaster::ModbusTCPMaster():
tcp(nullptr), tcp(nullptr),
nTransaction(0), nTransaction(0),
iaddr(""), iaddr(""),
force_disconnect(true) force_disconnect(true)
{ {
setCRCNoCheckit(true); setCRCNoCheckit(true);
// dlog->level(Debug::ANY); // dlog->level(Debug::ANY);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPMaster::~ModbusTCPMaster() ModbusTCPMaster::~ModbusTCPMaster()
{ {
if( isConnection() ) if( isConnection() )
disconnect(); disconnect();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusTCPMaster::getNextData( unsigned char* buf, size_t len ) size_t ModbusTCPMaster::getNextData( unsigned char* buf, size_t len )
{ {
return ModbusTCPCore::getNextData(tcp.get(), qrecv, buf, len ); return ModbusTCPCore::getNextData(tcp.get(), qrecv, buf, len );
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPMaster::setChannelTimeout( timeout_t msec ) void ModbusTCPMaster::setChannelTimeout( timeout_t msec )
{ {
if( !tcp ) if( !tcp )
return; return;
Poco::Timespan tm = UniSetTimer::millisecToPoco(msec); Poco::Timespan tm = UniSetTimer::millisecToPoco(msec);
Poco::Timespan old = tcp->getReceiveTimeout();; Poco::Timespan old = tcp->getReceiveTimeout();;
if( old.totalMicroseconds() == tm.totalMicroseconds() ) if( old.totalMicroseconds() == tm.totalMicroseconds() )
return; return;
tcp->setReceiveTimeout(tm); tcp->setReceiveTimeout(tm);
int oldKeepAlive = keepAliveTimeout; int oldKeepAlive = keepAliveTimeout;
keepAliveTimeout = (msec > 1000 ? msec / 1000 : 1); keepAliveTimeout = (msec > 1000 ? msec / 1000 : 1);
// т.к. каждый раз не вызывать дорогой системный вызов // т.к. каждый раз не вызывать дорогой системный вызов
// смотрим меняется ли значение // смотрим меняется ли значение
if( oldKeepAlive != keepAliveTimeout ) if( oldKeepAlive != keepAliveTimeout )
tcp->setKeepAliveParams(keepAliveTimeout); tcp->setKeepAliveParams(keepAliveTimeout);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPMaster::sendData( unsigned char* buf, size_t len ) mbErrCode ModbusTCPMaster::sendData( unsigned char* buf, size_t len )
{ {
return ModbusTCPCore::sendData(tcp.get(), buf, len); return ModbusTCPCore::sendData(tcp.get(), buf, len);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg, mbErrCode ModbusTCPMaster::query( ModbusAddr addr, ModbusMessage& msg,
ModbusMessage& reply, timeout_t timeout_msec ) ModbusMessage& reply, timeout_t timeout_msec )
{ {
try try
{ {
if( iaddr.empty() ) if( iaddr.empty() )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << iaddr << "(ModbusTCPMaster::query): unknown ip address for server..." << endl; dlog->warn() << iaddr << "(ModbusTCPMaster::query): unknown ip address for server..." << endl;
return erTimeOut; // erHardwareError return erTimeOut; // erHardwareError
} }
if( !isConnection() ) if( !isConnection() )
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << iaddr << "(ModbusTCPMaster::query): no connection.. reconnnect..." << endl; dlog->info() << iaddr << "(ModbusTCPMaster::query): no connection.. reconnnect..." << endl;
reconnect(); reconnect();
} }
if( !isConnection() ) if( !isConnection() )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << iaddr << "(ModbusTCPMaster::query): not connected to server..." << endl; dlog->warn() << iaddr << "(ModbusTCPMaster::query): not connected to server..." << endl;
return erTimeOut; return erTimeOut;
} }
assert(timeout_msec); assert(timeout_msec);
ptTimeout.setTiming(timeout_msec); ptTimeout.setTiming(timeout_msec);
tcp->setReceiveTimeout( UniSetTimer::millisecToPoco(timeout_msec) ); tcp->setReceiveTimeout( UniSetTimer::millisecToPoco(timeout_msec) );
msg.makeMBAPHeader(++nTransaction, crcNoCheckit); msg.makeMBAPHeader(++nTransaction, crcNoCheckit);
for( size_t i = 0; i < 2; i++ ) for( size_t i = 0; i < 2; i++ )
{ {
if( tcp->poll(UniSetTimer::millisecToPoco(timeout_msec), Poco::Net::Socket::SELECT_WRITE) ) if( tcp->poll(UniSetTimer::millisecToPoco(timeout_msec), Poco::Net::Socket::SELECT_WRITE) )
{ {
mbErrCode res = send(msg); mbErrCode res = send(msg);
if( res != erNoError ) if( res != erNoError )
return res; return res;
break; break;
} }
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(ModbusTCPMaster::query): no write pending.. reconnnect.." << endl; dlog->info() << "(ModbusTCPMaster::query): no write pending.. reconnnect.." << endl;
reconnect(); reconnect();
if( !isConnection() ) if( !isConnection() )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(ModbusTCPMaster::query): not connected to server..." << endl; dlog->warn() << "(ModbusTCPMaster::query): not connected to server..." << endl;
return erTimeOut; return erTimeOut;
} }
cleanInputStream(); cleanInputStream();
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(ModbusTCPMaster::query): no write pending.. reconnnect OK" << endl; dlog->info() << "(ModbusTCPMaster::query): no write pending.. reconnnect OK" << endl;
} }
if( timeout_msec != UniSetTimer::WaitUpTime ) if( timeout_msec != UniSetTimer::WaitUpTime )
{ {
timeout_msec = ptTimeout.getLeft(timeout_msec); timeout_msec = ptTimeout.getLeft(timeout_msec);
if( timeout_msec == 0 ) if( timeout_msec == 0 )
return erTimeOut; return erTimeOut;
ptTimeout.setTiming(timeout_msec); ptTimeout.setTiming(timeout_msec);
} }
// чистим очередь // чистим очередь
// cleanInputStream(); // cleanInputStream();
while( !qrecv.empty() ) while( !qrecv.empty() )
qrecv.pop(); qrecv.pop();
//tcp->sync(); //tcp->sync();
if( tcp->poll(UniSetTimer::millisecToPoco(timeout_msec), Poco::Net::Socket::SELECT_READ ) ) if( tcp->poll(UniSetTimer::millisecToPoco(timeout_msec), Poco::Net::Socket::SELECT_READ ) )
{ {
size_t ret = 0; size_t ret = 0;
while( !ptTimeout.checkTime() ) while( !ptTimeout.checkTime() )
{ {
ret = getNextData((unsigned char*)(&reply.mbaphead), sizeof(reply.mbaphead)); ret = getNextData((unsigned char*)(&reply.mbaphead), sizeof(reply.mbaphead));
if( ret == sizeof(reply.mbaphead) ) if( ret == sizeof(reply.mbaphead) )
break; break;
} }
if( ret > 0 && dlog->is_info() ) if( ret > 0 && dlog->is_info() )
{ {
dlog->info() << "(ModbusTCPMaster::query): recv tcp header(" << ret << "): "; dlog->info() << "(ModbusTCPMaster::query): recv tcp header(" << ret << "): ";
mbPrintMessage( dlog->info(false), (ModbusByte*)(&reply.mbaphead), sizeof(reply.mbaphead)); mbPrintMessage( dlog->info(false), (ModbusByte*)(&reply.mbaphead), sizeof(reply.mbaphead));
dlog->info(false) << endl; dlog->info(false) << endl;
} }
if( ret < sizeof(reply.mbaphead) ) if( ret < sizeof(reply.mbaphead) )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
{ {
try try
{ {
Poco::Net::SocketAddress ia = tcp->peerAddress(); Poco::Net::SocketAddress ia = tcp->peerAddress();
dlog->warn() << "(ModbusTCPMaster::query): ret=" << ret dlog->warn() << "(ModbusTCPMaster::query): ret=" << ret
<< " < rmh=" << sizeof(reply.mbaphead) << " < rmh=" << sizeof(reply.mbaphead)
<< " perr: " << ia.host().toString() << ":" << ia.port() << " perr: " << ia.host().toString() << ":" << ia.port()
<< endl; << endl;
} }
catch( const Poco::Net::NetException& ex ) catch( const Poco::Net::NetException& ex )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(query): tcp error: " << ex.displayText() << endl; dlog->warn() << "(query): tcp error: " << ex.displayText() << endl;
} }
} }
cleanInputStream(); cleanInputStream();
if( tcp ) if( tcp )
tcp->forceDisconnect(); tcp->forceDisconnect();
return erTimeOut; // return erHardwareError; return erTimeOut; // return erHardwareError;
} }
reply.swapHead(); reply.swapHead();
if( dlog->is_level9() ) if( dlog->is_level9() )
dlog->level9() << "(ModbusTCPMaster::query): ADU len=" << reply.aduLen() dlog->level9() << "(ModbusTCPMaster::query): ADU len=" << reply.aduLen()
<< endl; << endl;
if( reply.tID() != msg.tID() ) if( reply.tID() != msg.tID() )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(ModbusTCPMaster::query): tID=" << reply.tID() dlog->warn() << "(ModbusTCPMaster::query): tID=" << reply.tID()
<< " != " << msg.tID() << " != " << msg.tID()
<< " (len=" << reply.len() << ")" << " (len=" << reply.len() << ")"
<< endl; << endl;
cleanInputStream(); cleanInputStream();
return erBadReplyNodeAddress; return erBadReplyNodeAddress;
} }
if( reply.pID() != 0 ) if( reply.pID() != 0 )
{ {
cleanInputStream(); cleanInputStream();
return erBadReplyNodeAddress; return erBadReplyNodeAddress;
} }
// //
timeout_msec = ptTimeout.getLeft(timeout_msec); timeout_msec = ptTimeout.getLeft(timeout_msec);
if( timeout_msec <= 0 ) if( timeout_msec <= 0 )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(ModbusTCPMaster::query): processing reply timeout.." << endl; dlog->warn() << "(ModbusTCPMaster::query): processing reply timeout.." << endl;
return erTimeOut; // return erHardwareError; return erTimeOut; // return erHardwareError;
} }
//msg.aduhead = reply.aduhead; //msg.aduhead = reply.aduhead;
mbErrCode res = recv(addr, msg.func(), reply, timeout_msec); mbErrCode res = recv(addr, msg.func(), reply, timeout_msec);
if( force_disconnect ) if( force_disconnect )
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(query): disconnect.." << endl; dlog->info() << "(query): disconnect.." << endl;
// при штатном обмене..лучше дождаться конца "посылки".. // при штатном обмене..лучше дождаться конца "посылки"..
// поэтому применяем disconnect(), а не forceDisconnect() // поэтому применяем disconnect(), а не forceDisconnect()
// (с учётом выставленной опции setLinger(true)) // (с учётом выставленной опции setLinger(true))
if( tcp ) if( tcp )
tcp->disconnect(); tcp->disconnect();
} }
return res; return res;
} }
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(query): input pending timeout=" << timeout_msec << endl; dlog->info() << "(query): input pending timeout=" << timeout_msec << endl;
if( force_disconnect ) if( force_disconnect )
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(query): force disconnect.." << endl; dlog->info() << "(query): force disconnect.." << endl;
// cleanInputStream(); // cleanInputStream();
if( tcp ) if( tcp )
tcp->forceDisconnect(); tcp->forceDisconnect();
} }
return erTimeOut; return erTimeOut;
} }
catch( ModbusRTU::mbException& ex ) catch( ModbusRTU::mbException& ex )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(query): " << ex << endl; dlog->warn() << "(query): " << ex << endl;
} }
catch( SystemError& err ) catch( SystemError& err )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(query): " << err << endl; dlog->warn() << "(query): " << err << endl;
} }
catch( const uniset::CommFailed& ex ) catch( const uniset::CommFailed& ex )
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(query): " << ex << endl; dlog->crit() << "(query): " << ex << endl;
if( tcp ) if( tcp )
tcp->forceDisconnect(); tcp->forceDisconnect();
} }
catch( const Poco::Net::NetException& e ) catch( const Poco::Net::NetException& e )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(query): tcp error: " << e.displayText() << endl; dlog->warn() << "(query): tcp error: " << e.displayText() << endl;
} }
catch( const uniset::Exception& ex ) catch( const uniset::Exception& ex )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(query): " << ex << endl; dlog->warn() << "(query): " << ex << endl;
} }
catch( const std::exception& e ) catch( const std::exception& e )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(query): " << e.what() << std::endl; dlog->warn() << "(query): " << e.what() << std::endl;
} }
return erTimeOut; // erHardwareError return erTimeOut; // erHardwareError
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPMaster::cleanInputStream() void ModbusTCPMaster::cleanInputStream()
{ {
unsigned char buf[100]; unsigned char buf[100];
int ret = 0; int ret = 0;
try try
{ {
do do
{ {
ret = getNextData(buf, sizeof(buf)); ret = getNextData(buf, sizeof(buf));
} }
while( ret > 0); while( ret > 0);
} }
catch( ... ) {} catch( ... ) {}
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPMaster::cleanupChannel() void ModbusTCPMaster::cleanupChannel()
{ {
cleanInputStream(); cleanInputStream();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
string ModbusTCPMaster::getAddress() const string ModbusTCPMaster::getAddress() const
{ {
return iaddr; return iaddr;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
int ModbusTCPMaster::getPort() const int ModbusTCPMaster::getPort() const
{ {
return port; return port;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPMaster::setReadTimeout( timeout_t msec ) void ModbusTCPMaster::setReadTimeout( timeout_t msec )
{ {
readTimeout = msec; readTimeout = msec;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
timeout_t ModbusTCPMaster::getReadTimeout() const timeout_t ModbusTCPMaster::getReadTimeout() const
{ {
return readTimeout; return readTimeout;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPMaster::checkConnection( const std::string& ip, int port, int timeout_msec ) bool ModbusTCPMaster::checkConnection( const std::string& ip, int port, int timeout_msec )
{ {
try try
{ {
ostringstream s; ostringstream s;
s << ip << ":" << port; s << ip << ":" << port;
// Проверяем просто попыткой создать соединение.. // Проверяем просто попыткой создать соединение..
UTCPStream t; UTCPStream t;
t.create(ip, port, timeout_msec); t.create(ip, port, timeout_msec);
t.setKeepAliveParams( (timeout_msec > 1000 ? timeout_msec / 1000 : 1), 1, 1); t.setKeepAliveParams( (timeout_msec > 1000 ? timeout_msec / 1000 : 1), 1, 1);
t.setNoDelay(true); t.setNoDelay(true);
//t.shutdown(); //t.shutdown();
t.close(); t.close();
return true; return true;
} }
catch(...) catch(...)
{ {
} }
return false; return false;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPMaster::setForceDisconnect( bool s ) void ModbusTCPMaster::setForceDisconnect( bool s )
{ {
force_disconnect = s; force_disconnect = s;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPMaster::reconnect() bool ModbusTCPMaster::reconnect()
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(ModbusTCPMaster): reconnect " << iaddr << ":" << port << endl; dlog->info() << "(ModbusTCPMaster): reconnect " << iaddr << ":" << port << endl;
if( tcp ) if( tcp )
{ {
tcp->forceDisconnect(); tcp->forceDisconnect();
tcp = nullptr; tcp = nullptr;
} }
return connect(iaddr, port, true); return connect(iaddr, port, true);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPMaster::connect( const std::string& addr, int _port, bool closeOldConnection ) noexcept bool ModbusTCPMaster::connect( const std::string& addr, int _port, bool closeOldConnection ) noexcept
{ {
try try
{ {
Net::SocketAddress sa(addr, _port); Net::SocketAddress sa(addr, _port);
return connect(sa, _port, closeOldConnection); return connect(sa, _port, closeOldConnection);
} }
catch( const std::exception& e ) catch( const std::exception& e )
{ {
if( dlog->debugging(Debug::CRIT) ) if( dlog->debugging(Debug::CRIT) )
{ {
ostringstream s; ostringstream s;
s << "(ModbusTCPMaster): connect " << iaddr << ":" << port << " error: " << e.what(); s << "(ModbusTCPMaster): connect " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << s.str() << std::endl; dlog->crit() << s.str() << std::endl;
} }
} }
if( closeOldConnection && tcp ) if( closeOldConnection && tcp )
{ {
forceDisconnect(); forceDisconnect();
tcp = nullptr; tcp = nullptr;
} }
return false; return false;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port, bool closeOldConnection ) noexcept bool ModbusTCPMaster::connect( const Poco::Net::SocketAddress& addr, int _port, bool closeOldConnection ) noexcept
{ {
if( tcp ) if( tcp )
{ {
if( !closeOldConnection ) if( !closeOldConnection )
return false; return false;
//disconnect(); //disconnect();
forceDisconnect(); forceDisconnect();
tcp = nullptr; tcp = nullptr;
} }
iaddr = addr.host().toString(); iaddr = addr.host().toString();
port = _port; port = _port;
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << "(ModbusTCPMaster): connect to " << iaddr << ":" << port << endl; dlog->info() << "(ModbusTCPMaster): connect to " << iaddr << ":" << port << endl;
try try
{ {
tcp = make_shared<UTCPStream>(); tcp = make_shared<UTCPStream>();
tcp->create(iaddr, port, 500); tcp->create(iaddr, port, 500);
//tcp->connect(addr,500); //tcp->connect(addr,500);
tcp->setReceiveTimeout(UniSetTimer::millisecToPoco(replyTimeOut_ms)); tcp->setReceiveTimeout(UniSetTimer::millisecToPoco(replyTimeOut_ms));
tcp->setKeepAlive(true); // tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms / 1000 : 1)); tcp->setKeepAlive(true); // tcp->setKeepAliveParams((replyTimeOut_ms > 1000 ? replyTimeOut_ms / 1000 : 1));
tcp->setNoDelay(true); tcp->setNoDelay(true);
return true; return true;
} }
catch( Poco::TimeoutException& ex) catch( Poco::TimeoutException& ex)
{ {
if( dlog->debugging(Debug::CRIT) ) if( dlog->debugging(Debug::CRIT) )
{ {
ostringstream s; ostringstream s;
s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " timeout exception"; s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " timeout exception";
dlog->crit() << s.str() << std::endl; dlog->crit() << s.str() << std::endl;
} }
} }
catch( Poco::Net::NetException& ex) catch( Poco::Net::NetException& ex)
{ {
if( dlog->debugging(Debug::CRIT) ) if( dlog->debugging(Debug::CRIT) )
{ {
ostringstream s; ostringstream s;
s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " error: " << ex.displayText(); s << "(ModbusTCPMaster): create connection " << iaddr << ":" << port << " error: " << ex.displayText();
dlog->crit() << s.str() << std::endl; dlog->crit() << s.str() << std::endl;
} }
} }
catch( const std::exception& e ) catch( const std::exception& e )
{ {
if( dlog->debugging(Debug::CRIT) ) if( dlog->debugging(Debug::CRIT) )
{ {
ostringstream s; ostringstream s;
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: " << e.what(); s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: " << e.what();
dlog->crit() << s.str() << std::endl; dlog->crit() << s.str() << std::endl;
} }
} }
catch( ... ) catch( ... )
{ {
if( dlog->debugging(Debug::CRIT) ) if( dlog->debugging(Debug::CRIT) )
{ {
ostringstream s; ostringstream s;
s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: catch ..."; s << "(ModbusTCPMaster): connection " << iaddr << ":" << port << " error: catch ...";
dlog->crit() << s.str() << std::endl; dlog->crit() << s.str() << std::endl;
} }
} }
tcp = nullptr; tcp = nullptr;
return false; return false;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPMaster::disconnect() void ModbusTCPMaster::disconnect()
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << iaddr << "(ModbusTCPMaster): disconnect (" << iaddr << ":" << port << ")." << endl; dlog->info() << iaddr << "(ModbusTCPMaster): disconnect (" << iaddr << ":" << port << ")." << endl;
if( !tcp ) if( !tcp )
return; return;
tcp->disconnect(); // close(); tcp->disconnect(); // close();
tcp = nullptr; tcp = nullptr;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPMaster::forceDisconnect() void ModbusTCPMaster::forceDisconnect()
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << iaddr << "(ModbusTCPMaster): FORCE disconnect (" << iaddr << ":" << port << ")." << endl; dlog->info() << iaddr << "(ModbusTCPMaster): FORCE disconnect (" << iaddr << ":" << port << ")." << endl;
if( !tcp ) if( !tcp )
return; return;
tcp->forceDisconnect(); tcp->forceDisconnect();
tcp = nullptr; tcp = nullptr;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPMaster::isConnection() const bool ModbusTCPMaster::isConnection() const
{ {
return tcp && tcp->isConnected(); return tcp && tcp->isConnected();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -23,451 +23,460 @@ ...@@ -23,451 +23,460 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace uniset; using namespace uniset;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPServer::ModbusTCPServer( const std::string& ia, int _port ): ModbusTCPServer::ModbusTCPServer( const std::string& ia, int _port ):
port(_port), port(_port),
iaddr(ia), iaddr(ia),
myname(""), myname(""),
ignoreAddr(false), ignoreAddr(false),
maxSessions(10), maxSessions(10),
sessCount(0), sessCount(0),
sessTimeout(10000) sessTimeout(10000)
{ {
setCRCNoCheckit(true); setCRCNoCheckit(true);
{ {
ostringstream s; ostringstream s;
s << iaddr << ":" << port; s << iaddr << ":" << port;
myname = s.str(); myname = s.str();
} }
io.set<ModbusTCPServer, &ModbusTCPServer::ioAccept>(this); io.set<ModbusTCPServer, &ModbusTCPServer::ioAccept>(this);
ioTimer.set<ModbusTCPServer, &ModbusTCPServer::onTimer>(this); ioTimer.set<ModbusTCPServer, &ModbusTCPServer::onTimer>(this);
sockTimeout.set<ModbusTCPServer, &ModbusTCPServer::onSocketTimeout>(this); sockTimeout.set<ModbusTCPServer, &ModbusTCPServer::onSocketTimeout>(this);
asyncResetSockTimeout.set<ModbusTCPServer, &ModbusTCPServer::onSocketResetTimeout>(this); asyncResetSockTimeout.set<ModbusTCPServer, &ModbusTCPServer::onSocketResetTimeout>(this);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPServer::~ModbusTCPServer() ModbusTCPServer::~ModbusTCPServer()
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::setMaxSessions( size_t num ) void ModbusTCPServer::setMaxSessions( size_t num )
{ {
if( num < sessCount ) if( num < sessCount )
{ {
std::lock_guard<std::mutex> l(sMutex); std::lock_guard<std::mutex> l(sMutex);
int k = sessCount - num; int k = sessCount - num;
int d = 0; int d = 0;
for( SessionList::reverse_iterator i = slist.rbegin(); d < k && i != slist.rend(); ++i, d++ ) for( SessionList::reverse_iterator i = slist.rbegin(); d < k && i != slist.rend(); ++i, d++ )
(*i).reset(); (*i).reset();
sessCount = num; sessCount = num;
} }
maxSessions = num; maxSessions = num;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusTCPServer::getMaxSessions() const noexcept size_t ModbusTCPServer::getMaxSessions() const noexcept
{ {
return maxSessions; return maxSessions;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusTCPServer::getCountSessions() const noexcept size_t ModbusTCPServer::getCountSessions() const noexcept
{ {
return sessCount; return sessCount;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::setSessionTimeout( timeout_t msec ) void ModbusTCPServer::setSessionTimeout( timeout_t msec )
{ {
sessTimeout = msec; sessTimeout = msec;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
timeout_t ModbusTCPServer::getSessionTimeout() const noexcept timeout_t ModbusTCPServer::getSessionTimeout() const noexcept
{ {
return sessTimeout; return sessTimeout;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPServer::run( const std::unordered_set<ModbusAddr>& _vmbaddr ) bool ModbusTCPServer::run( const std::unordered_set<ModbusAddr>& _vmbaddr )
{ {
vmbaddr = _vmbaddr; vmbaddr = _vmbaddr;
return evrun(); return evrun();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPServer::async_run( const std::unordered_set<ModbusAddr>& _vmbaddr ) bool ModbusTCPServer::async_run( const std::unordered_set<ModbusAddr>& _vmbaddr )
{ {
vmbaddr = _vmbaddr; vmbaddr = _vmbaddr;
return async_evrun(); return async_evrun();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPServer::isActive() const bool ModbusTCPServer::isActive() const
{ {
return evIsActive() && sock; return evIsActive() && sock;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::createSocket() void ModbusTCPServer::createSocket()
{ {
try try
{ {
auto tmpSock = make_shared<UTCPSocket>(iaddr, port); auto tmpSock = make_shared<UTCPSocket>(iaddr, port);
if( sock ) if( sock )
sock.reset(); sock.reset();
sock = tmpSock; sock = tmpSock;
} }
catch( const Poco::Net::NetException& ex ) catch( const Poco::Net::NetException& ex )
{ {
ostringstream err; ostringstream err;
err << "(ModbusTCPServer::createSocket): connect " << iaddr << ":" << port << " err: " << ex.what(); err << "(ModbusTCPServer::createSocket): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl; dlog->crit() << err.str() << endl;
throw uniset::SystemError(err.str()); throw uniset::SystemError(err.str());
} }
catch( const std::exception& ex ) catch( const std::exception& ex )
{ {
ostringstream err; ostringstream err;
err << "(ModbusTCPServer::createSocket): connect " << iaddr << ":" << port << " err: " << ex.what(); err << "(ModbusTCPServer::createSocket): connect " << iaddr << ":" << port << " err: " << ex.what();
dlog->crit() << err.str() << endl; dlog->crit() << err.str() << endl;
throw uniset::SystemError(err.str()); throw uniset::SystemError(err.str());
} }
sock->setBlocking(false); sock->setBlocking(false);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::evprepare() void ModbusTCPServer::evprepare()
{ {
createSocket(); createSocket();
io.set(loop); io.set(loop);
io.start(sock->getSocket(), ev::READ); io.start(sock->getSocket(), ev::READ);
asyncResetSockTimeout.set(loop); asyncResetSockTimeout.set(loop);
asyncResetSockTimeout.start(); asyncResetSockTimeout.start();
ioTimer.set(loop); ioTimer.set(loop);
if( tmTime_msec != UniSetTimer::WaitUpTime )
ioTimer.start(0, tmTime); if( tmTime_msec != UniSetTimer::WaitUpTime )
ioTimer.start(0, tmTime);
sockTimeout.set(loop); sockTimeout.set(loop);
if( socketTimeout_msec > 0 && socketTimeout_msec != UniSetTimer::WaitUpTime ) if( socketTimeout_msec > 0 && socketTimeout_msec != UniSetTimer::WaitUpTime )
sockTimeout.start(0, tmSockTimeout); sockTimeout.start(0, tmSockTimeout);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::terminate() void ModbusTCPServer::terminate()
{ {
evstop(); evstop();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::evfinish() void ModbusTCPServer::evfinish()
{ {
if( !io.is_active() ) if( !io.is_active() )
return; return;
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << myname << "(ModbusTCPServer): terminate..." << endl; dlog->info() << myname << "(ModbusTCPServer): terminate..." << endl;
ioTimer.stop(); ioTimer.stop();
io.stop(); io.stop();
sockTimeout.stop(); sockTimeout.stop();
asyncResetSockTimeout.stop(); asyncResetSockTimeout.stop();
auto lst(slist); auto lst(slist);
// Копируем сперва себе список сессий.. // Копируем сперва себе список сессий..
// т.к при вызове terminate() // т.к при вызове terminate()
// у Session будет вызван сигнал "final" // у Session будет вызван сигнал "final"
// который приведёт к вызову sessionFinished().. // который приведёт к вызову sessionFinished()..
// в котором этот список будет меняться (удалится сессия из списка) // в котором этот список будет меняться (удалится сессия из списка)
for( const auto& s : lst ) for( const auto& s : lst )
{ {
try try
{ {
s->terminate(); s->terminate();
} }
catch( std::exception& ex ) {} catch( std::exception& ex ) {}
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::sessionFinished( const ModbusTCPSession* s ) void ModbusTCPServer::sessionFinished( const ModbusTCPSession* s )
{ {
std::lock_guard<std::mutex> l(sMutex); std::lock_guard<std::mutex> l(sMutex);
for( auto i = slist.begin(); i != slist.end(); ++i ) for( auto i = slist.begin(); i != slist.end(); ++i )
{ {
if( (*i).get() == s ) if( (*i).get() == s )
{ {
slist.erase(i); slist.erase(i);
sessCount--; sessCount--;
asyncResetSockTimeout.send(); asyncResetSockTimeout.send();
return; return;
} }
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::getSessions( Sessions& lst ) void ModbusTCPServer::getSessions( Sessions& lst )
{ {
std::lock_guard<std::mutex> l(sMutex); std::lock_guard<std::mutex> l(sMutex);
for( const auto& i : slist ) for( const auto& i : slist )
lst.emplace_back( i->getClientAddress(), i->getAskCount() ); lst.emplace_back( i->getClientAddress(), i->getAskCount() );
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
string ModbusTCPServer::getInetAddress() const noexcept string ModbusTCPServer::getInetAddress() const noexcept
{ {
return iaddr; return iaddr;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
int ModbusTCPServer::getInetPort() const noexcept int ModbusTCPServer::getInetPort() const noexcept
{ {
return port; return port;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusTCPServer::getConnectionCount() const noexcept size_t ModbusTCPServer::getConnectionCount() const noexcept
{ {
return connCount; return connCount;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPServer::TimerSignal ModbusTCPServer::signal_timer() ModbusTCPServer::TimerSignal ModbusTCPServer::signal_timer()
{ {
return m_timer_signal; return m_timer_signal;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::setTimer( timeout_t msec ) void ModbusTCPServer::setTimer( timeout_t msec )
{ {
tmTime_msec = msec; tmTime_msec = msec;
if( msec == UniSetTimer::WaitUpTime ) if( msec == UniSetTimer::WaitUpTime )
{ {
tmTime = 0; tmTime = 0;
if( ioTimer.is_active() ) if( ioTimer.is_active() )
ioTimer.stop(); ioTimer.stop();
} }
else else
{ {
tmTime = (double)msec / 1000.; tmTime = (double)msec / 1000.;
if( ioTimer.is_active() ) if( ioTimer.is_active() )
ioTimer.start( 0, tmTime ); ioTimer.start( 0, tmTime );
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
timeout_t ModbusTCPServer::getTimer() const noexcept timeout_t ModbusTCPServer::getTimer() const noexcept
{ {
return tmTime_msec; return tmTime_msec;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServer::setSocketTimeout( timeout_t msec ) void ModbusTCPServer::setSocketTimeout( timeout_t msec )
{ {
socketTimeout_msec = msec; socketTimeout_msec = msec;
if( msec == UniSetTimer::WaitUpTime || msec == 0 )
{ if( msec == UniSetTimer::WaitUpTime || msec == 0 )
socketTimeout_msec = 0; {
if( sockTimeout.is_active() ) socketTimeout_msec = 0;
sockTimeout.stop();
} if( sockTimeout.is_active() )
else sockTimeout.stop();
{ }
tmSockTimeout = (double)msec / 1000.; else
if( sockTimeout.is_active() ) {
sockTimeout.start( 0, tmSockTimeout ); tmSockTimeout = (double)msec / 1000.;
}
} if( sockTimeout.is_active() )
// ------------------------------------------------------------------------ sockTimeout.start( 0, tmSockTimeout );
timeout_t ModbusTCPServer::getSocketTimeout() const noexcept }
{ }
return socketTimeout_msec; // ------------------------------------------------------------------------
} timeout_t ModbusTCPServer::getSocketTimeout() const noexcept
// ------------------------------------------------------------------------- {
void ModbusTCPServer::iowait( timeout_t msec ) return socketTimeout_msec;
{ }
ptWait.setTiming(msec); // -------------------------------------------------------------------------
void ModbusTCPServer::iowait( timeout_t msec )
while( !ptWait.checkTime() ) {
io.loop.iteration(); ptWait.setTiming(msec);
}
// ------------------------------------------------------------------------- while( !ptWait.checkTime() )
void ModbusTCPServer::ioAccept(ev::io& watcher, int revents) io.loop.iteration();
{ }
if (EV_ERROR & revents) // -------------------------------------------------------------------------
{ void ModbusTCPServer::ioAccept(ev::io& watcher, int revents)
if( dlog->is_crit() ) {
dlog->crit() << myname << "(ModbusTCPServer::ioAccept): invalid event" << endl; if (EV_ERROR & revents)
{
return; if( dlog->is_crit() )
} dlog->crit() << myname << "(ModbusTCPServer::ioAccept): invalid event" << endl;
if( !evIsActive() ) return;
{ }
if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::ioAccept): terminate work.." << endl; if( !evIsActive() )
{
sock->close(); if( dlog->is_crit() )
return; dlog->crit() << myname << "(ModbusTCPServer::ioAccept): terminate work.." << endl;
}
sock->close();
if( sessCount >= maxSessions ) return;
{ }
if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::ioAccept): session limit(" << maxSessions << ")" << endl; if( sessCount >= maxSessions )
{
sock->close(); if( dlog->is_crit() )
return; dlog->crit() << myname << "(ModbusTCPServer::ioAccept): session limit(" << maxSessions << ")" << endl;
}
sock->close();
if( dlog->is_info() ) return;
dlog->info() << myname << "(ModbusTCPServer): new connection.." << endl; }
try if( dlog->is_info() )
{ dlog->info() << myname << "(ModbusTCPServer): new connection.." << endl;
Poco::Net::StreamSocket ss = sock->acceptConnection();
try
connCount++; {
Poco::Net::StreamSocket ss = sock->acceptConnection();
if( sockTimeout.is_active() )
sockTimeout.again(); connCount++;
auto s = make_shared<ModbusTCPSession>(ss, vmbaddr, sessTimeout); if( sockTimeout.is_active() )
s->connectReadCoil( sigc::mem_fun(this, &ModbusTCPServer::readCoilStatus) ); sockTimeout.again();
s->connectReadInputStatus( sigc::mem_fun(this, &ModbusTCPServer::readInputStatus) );
s->connectReadOutput( sigc::mem_fun(this, &ModbusTCPServer::readOutputRegisters) ); auto s = make_shared<ModbusTCPSession>(ss, vmbaddr, sessTimeout);
s->connectReadInput( sigc::mem_fun(this, &ModbusTCPServer::readInputRegisters) ); s->connectReadCoil( sigc::mem_fun(this, &ModbusTCPServer::readCoilStatus) );
s->connectForceSingleCoil( sigc::mem_fun(this, &ModbusTCPServer::forceSingleCoil) ); s->connectReadInputStatus( sigc::mem_fun(this, &ModbusTCPServer::readInputStatus) );
s->connectForceCoils( sigc::mem_fun(this, &ModbusTCPServer::forceMultipleCoils) ); s->connectReadOutput( sigc::mem_fun(this, &ModbusTCPServer::readOutputRegisters) );
s->connectWriteOutput( sigc::mem_fun(this, &ModbusTCPServer::writeOutputRegisters) ); s->connectReadInput( sigc::mem_fun(this, &ModbusTCPServer::readInputRegisters) );
s->connectWriteSingleOutput( sigc::mem_fun(this, &ModbusTCPServer::writeOutputSingleRegister) ); s->connectForceSingleCoil( sigc::mem_fun(this, &ModbusTCPServer::forceSingleCoil) );
s->connectMEIRDI( sigc::mem_fun(this, &ModbusTCPServer::read4314) ); s->connectForceCoils( sigc::mem_fun(this, &ModbusTCPServer::forceMultipleCoils) );
s->connectSetDateTime( sigc::mem_fun(this, &ModbusTCPServer::setDateTime) ); s->connectWriteOutput( sigc::mem_fun(this, &ModbusTCPServer::writeOutputRegisters) );
s->connectDiagnostics( sigc::mem_fun(this, &ModbusTCPServer::diagnostics) ); s->connectWriteSingleOutput( sigc::mem_fun(this, &ModbusTCPServer::writeOutputSingleRegister) );
s->connectFileTransfer( sigc::mem_fun(this, &ModbusTCPServer::fileTransfer) ); s->connectMEIRDI( sigc::mem_fun(this, &ModbusTCPServer::read4314) );
s->connectJournalCommand( sigc::mem_fun(this, &ModbusTCPServer::journalCommand) ); s->connectSetDateTime( sigc::mem_fun(this, &ModbusTCPServer::setDateTime) );
s->connectRemoteService( sigc::mem_fun(this, &ModbusTCPServer::remoteService) ); s->connectDiagnostics( sigc::mem_fun(this, &ModbusTCPServer::diagnostics) );
s->connectFileTransfer( sigc::mem_fun(this, &ModbusTCPServer::fileTransfer) ); s->connectFileTransfer( sigc::mem_fun(this, &ModbusTCPServer::fileTransfer) );
s->setAfterSendPause(aftersend_msec); s->connectJournalCommand( sigc::mem_fun(this, &ModbusTCPServer::journalCommand) );
s->setReplyTimeout(replyTimeout_ms); s->connectRemoteService( sigc::mem_fun(this, &ModbusTCPServer::remoteService) );
s->setRecvTimeout(recvTimeOut_ms); s->connectFileTransfer( sigc::mem_fun(this, &ModbusTCPServer::fileTransfer) );
s->setSleepPause(sleepPause_msec); s->setAfterSendPause(aftersend_msec);
s->setCleanBeforeSend(cleanBeforeSend); s->setReplyTimeout(replyTimeout_ms);
s->setSessionTimeout( (double)sessTimeout / 1000. ); s->setRecvTimeout(recvTimeOut_ms);
s->signal_post_receive().connect( sigc::mem_fun(this, &ModbusTCPServer::postReceiveEvent) ); s->setSleepPause(sleepPause_msec);
s->signal_pre_receive().connect( sigc::mem_fun(this, &ModbusTCPServer::preReceiveEvent) ); s->setCleanBeforeSend(cleanBeforeSend);
s->setSessionTimeout( (double)sessTimeout / 1000. );
s->setLog(dlog); s->signal_post_receive().connect( sigc::mem_fun(this, &ModbusTCPServer::postReceiveEvent) );
s->connectFinalSession( sigc::mem_fun(this, &ModbusTCPServer::sessionFinished) ); s->signal_pre_receive().connect( sigc::mem_fun(this, &ModbusTCPServer::preReceiveEvent) );
{ s->setLog(dlog);
std::lock_guard<std::mutex> l(sMutex); s->connectFinalSession( sigc::mem_fun(this, &ModbusTCPServer::sessionFinished) );
slist.push_back(s);
} {
std::lock_guard<std::mutex> l(sMutex);
s->run(loop); slist.push_back(s);
sessCount++; }
}
catch( std::exception& ex ) s->run(loop);
{ sessCount++;
if( dlog->is_crit() ) }
dlog->crit() << myname << "(ModbusTCPServer): new connection error: " << ex.what() << endl; catch( std::exception& ex )
} {
} if( dlog->is_crit() )
// ------------------------------------------------------------------------- dlog->crit() << myname << "(ModbusTCPServer): new connection error: " << ex.what() << endl;
void ModbusTCPServer::onTimer( ev::timer& t, int revents ) }
{ }
if (EV_ERROR & revents) // -------------------------------------------------------------------------
{ void ModbusTCPServer::onTimer( ev::timer& t, int revents )
if( dlog->is_crit() ) {
dlog->crit() << myname << "(ModbusTCPServer::ioTimer): invalid event" << endl; if (EV_ERROR & revents)
{
return; if( dlog->is_crit() )
} dlog->crit() << myname << "(ModbusTCPServer::ioTimer): invalid event" << endl;
try return;
{ }
m_timer_signal.emit();
} try
catch( std::exception& ex ) {
{ m_timer_signal.emit();
if( dlog->is_crit() ) }
dlog->crit() << myname << "(onTimer): " << ex.what() << endl; catch( std::exception& ex )
} {
} if( dlog->is_crit() )
// ------------------------------------------------------------------------- dlog->crit() << myname << "(onTimer): " << ex.what() << endl;
void ModbusTCPServer::onSocketResetTimeout( ev::async& watcher, int revents ) noexcept }
{ }
if( EV_ERROR & revents ) // -------------------------------------------------------------------------
{ void ModbusTCPServer::onSocketResetTimeout( ev::async& watcher, int revents ) noexcept
if( dlog->is_crit() ) {
dlog->crit() << myname << "(ModbusTCPServer::onSocketResetTimeout): invalid event" << endl; if( EV_ERROR & revents )
{
return; if( dlog->is_crit() )
} dlog->crit() << myname << "(ModbusTCPServer::onSocketResetTimeout): invalid event" << endl;
if( dlog->is_info() ) return;
dlog->info() << myname << "(ModbusTCPServer::onSocketResetTimeout): reset socket timeout.." << endl; }
if( sockTimeout.is_active() ) if( dlog->is_info() )
sockTimeout.again(); dlog->info() << myname << "(ModbusTCPServer::onSocketResetTimeout): reset socket timeout.." << endl;
}
// ------------------------------------------------------------------------- if( sockTimeout.is_active() )
void ModbusTCPServer::onSocketTimeout( ev::timer& t, int revents ) sockTimeout.again();
{ }
if (EV_ERROR & revents) // -------------------------------------------------------------------------
{ void ModbusTCPServer::onSocketTimeout( ev::timer& t, int revents )
if( dlog->is_crit() ) {
dlog->crit() << myname << "(ModbusTCPServer::onSocketTimeout): invalid event" << endl; if (EV_ERROR & revents)
return; {
} if( dlog->is_crit() )
dlog->crit() << myname << "(ModbusTCPServer::onSocketTimeout): invalid event" << endl;
{
std::lock_guard<std::mutex> l(sMutex); return;
if( !slist.empty()) }
{
if( dlog->is_info() ) {
dlog->info() << myname << "(ModbusTCPServer::onSocketTimeout): check socket [OK].." << endl; std::lock_guard<std::mutex> l(sMutex);
t.again(); if( !slist.empty())
return; {
} if( dlog->is_info() )
} dlog->info() << myname << "(ModbusTCPServer::onSocketTimeout): check socket [OK].." << endl;
if( dlog->is_warn() ) t.again();
dlog->warn() << myname << "(ModbusTCPServer::onSocketTimeout): no connections.. recreate socket.." << endl; return;
}
try }
{
createSocket(); if( dlog->is_warn() )
if( io.is_active() ) dlog->warn() << myname << "(ModbusTCPServer::onSocketTimeout): no connections.. recreate socket.." << endl;
io.stop();
try
io.start(sock->getSocket(), ev::READ); {
} createSocket();
catch( std::exception& ex )
{ if( io.is_active() )
if( dlog->is_crit() ) io.stop();
dlog->crit() << myname << "(ModbusTCPServer::onSocketTimeout): recreate socket ERROR: " << ex.what() << endl;
} io.start(sock->getSocket(), ev::READ);
}
t.again(); catch( std::exception& ex )
} {
// ------------------------------------------------------------------------- if( dlog->is_crit() )
mbErrCode ModbusTCPServer::realReceive( const std::unordered_set<ModbusAddr>& vaddr, timeout_t msecTimeout ) dlog->crit() << myname << "(ModbusTCPServer::onSocketTimeout): recreate socket ERROR: " << ex.what() << endl;
{ }
return ModbusRTU::erOperationFailed;
} t.again();
// ------------------------------------------------------------------------- }
void ModbusTCPServer::postReceiveEvent( mbErrCode res ) // -------------------------------------------------------------------------
{ mbErrCode ModbusTCPServer::realReceive( const std::unordered_set<ModbusAddr>& vaddr, timeout_t msecTimeout )
m_post_signal.emit(res); {
} return ModbusRTU::erOperationFailed;
// ------------------------------------------------------------------------- }
mbErrCode ModbusTCPServer::preReceiveEvent(const std::unordered_set<ModbusAddr> vaddr, timeout_t tout) // -------------------------------------------------------------------------
{ void ModbusTCPServer::postReceiveEvent( mbErrCode res )
if( m_pre_signal.empty() ) {
return ModbusRTU::erNoError; m_post_signal.emit(res);
}
return m_pre_signal.emit(vaddr, tout); // -------------------------------------------------------------------------
} mbErrCode ModbusTCPServer::preReceiveEvent(const std::unordered_set<ModbusAddr> vaddr, timeout_t tout)
// ------------------------------------------------------------------------- {
if( m_pre_signal.empty() )
return ModbusRTU::erNoError;
return m_pre_signal.emit(vaddr, tout);
}
// -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -18,163 +18,163 @@ ...@@ -18,163 +18,163 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace std; using namespace std;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPServerSlot::ModbusTCPServerSlot(const string& ia, int port ): ModbusTCPServerSlot::ModbusTCPServerSlot(const string& ia, int port ):
ModbusTCPServer(ia, port) ModbusTCPServer(ia, port)
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPServerSlot::~ModbusTCPServerSlot() ModbusTCPServerSlot::~ModbusTCPServerSlot()
{ {
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::readCoilStatus( ReadCoilMessage& query, mbErrCode ModbusTCPServerSlot::readCoilStatus( ReadCoilMessage& query,
ReadCoilRetMessage& reply ) ReadCoilRetMessage& reply )
{ {
if( !slReadCoil ) if( !slReadCoil )
return erOperationFailed; return erOperationFailed;
return slReadCoil(query, reply); return slReadCoil(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::readInputStatus( ReadInputStatusMessage& query, mbErrCode ModbusTCPServerSlot::readInputStatus( ReadInputStatusMessage& query,
ReadInputStatusRetMessage& reply ) ReadInputStatusRetMessage& reply )
{ {
if( !slReadInputStatus ) if( !slReadInputStatus )
return erOperationFailed; return erOperationFailed;
return slReadInputStatus(query, reply); return slReadInputStatus(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::readOutputRegisters( ReadOutputMessage& query, mbErrCode ModbusTCPServerSlot::readOutputRegisters( ReadOutputMessage& query,
ReadOutputRetMessage& reply ) ReadOutputRetMessage& reply )
{ {
if( !slReadOutputs ) if( !slReadOutputs )
return erOperationFailed; return erOperationFailed;
return slReadOutputs(query, reply); return slReadOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::readInputRegisters( ReadInputMessage& query, mbErrCode ModbusTCPServerSlot::readInputRegisters( ReadInputMessage& query,
ReadInputRetMessage& reply ) ReadInputRetMessage& reply )
{ {
if( !slReadInputs ) if( !slReadInputs )
return erOperationFailed; return erOperationFailed;
return slReadInputs(query, reply); return slReadInputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::forceMultipleCoils( ForceCoilsMessage& query, mbErrCode ModbusTCPServerSlot::forceMultipleCoils( ForceCoilsMessage& query,
ForceCoilsRetMessage& reply ) ForceCoilsRetMessage& reply )
{ {
if( !slForceCoils ) if( !slForceCoils )
return erOperationFailed; return erOperationFailed;
return slForceCoils(query, reply); return slForceCoils(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::writeOutputRegisters( WriteOutputMessage& query, mbErrCode ModbusTCPServerSlot::writeOutputRegisters( WriteOutputMessage& query,
WriteOutputRetMessage& reply ) WriteOutputRetMessage& reply )
{ {
if( !slWriteOutputs ) if( !slWriteOutputs )
return erOperationFailed; return erOperationFailed;
return slWriteOutputs(query, reply); return slWriteOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::diagnostics( DiagnosticMessage& query, mbErrCode ModbusTCPServerSlot::diagnostics( DiagnosticMessage& query,
DiagnosticRetMessage& reply ) DiagnosticRetMessage& reply )
{ {
if( !slDiagnostics ) if( !slDiagnostics )
return erOperationFailed; return erOperationFailed;
return slDiagnostics(query, reply); return slDiagnostics(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPServerSlot::read4314( ModbusRTU::MEIMessageRDI& query, ModbusRTU::mbErrCode ModbusTCPServerSlot::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply ) ModbusRTU::MEIMessageRetRDI& reply )
{ {
if( !slMEIRDI ) if( !slMEIRDI )
return erOperationFailed; return erOperationFailed;
return slMEIRDI(query, reply); return slMEIRDI(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::forceSingleCoil( ForceSingleCoilMessage& query, mbErrCode ModbusTCPServerSlot::forceSingleCoil( ForceSingleCoilMessage& query,
ForceSingleCoilRetMessage& reply ) ForceSingleCoilRetMessage& reply )
{ {
if( !slForceSingleCoil ) if( !slForceSingleCoil )
return erOperationFailed; return erOperationFailed;
return slForceSingleCoil(query, reply); return slForceSingleCoil(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::writeOutputSingleRegister( WriteSingleOutputMessage& query, mbErrCode ModbusTCPServerSlot::writeOutputSingleRegister( WriteSingleOutputMessage& query,
WriteSingleOutputRetMessage& reply ) WriteSingleOutputRetMessage& reply )
{ {
if( !slWriteSingleOutputs ) if( !slWriteSingleOutputs )
return erOperationFailed; return erOperationFailed;
return slWriteSingleOutputs(query, reply); return slWriteSingleOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPServerSlot::journalCommand( JournalCommandMessage& query, mbErrCode ModbusTCPServerSlot::journalCommand( JournalCommandMessage& query,
JournalCommandRetMessage& reply ) JournalCommandRetMessage& reply )
{ {
if( !slJournalCommand ) if( !slJournalCommand )
return erOperationFailed; return erOperationFailed;
return slJournalCommand(query, reply); return slJournalCommand(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPServerSlot::setDateTime( ModbusRTU::SetDateTimeMessage& query, ModbusRTU::mbErrCode ModbusTCPServerSlot::setDateTime( ModbusRTU::SetDateTimeMessage& query,
ModbusRTU::SetDateTimeRetMessage& reply ) ModbusRTU::SetDateTimeRetMessage& reply )
{ {
if( !slSetDateTime ) if( !slSetDateTime )
return erOperationFailed; return erOperationFailed;
return slSetDateTime(query, reply); return slSetDateTime(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPServerSlot::remoteService( ModbusRTU::RemoteServiceMessage& query, ModbusRTU::mbErrCode ModbusTCPServerSlot::remoteService( ModbusRTU::RemoteServiceMessage& query,
ModbusRTU::RemoteServiceRetMessage& reply ) ModbusRTU::RemoteServiceRetMessage& reply )
{ {
if( !slRemoteService ) if( !slRemoteService )
return erOperationFailed; return erOperationFailed;
return slRemoteService(query, reply); return slRemoteService(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPServerSlot::fileTransfer( ModbusRTU::FileTransferMessage& query, ModbusRTU::mbErrCode ModbusTCPServerSlot::fileTransfer( ModbusRTU::FileTransferMessage& query,
ModbusRTU::FileTransferRetMessage& reply ) ModbusRTU::FileTransferRetMessage& reply )
{ {
if( !slFileTransfer ) if( !slFileTransfer )
return erOperationFailed; return erOperationFailed;
return slFileTransfer(query, reply); return slFileTransfer(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPServerSlot::terminate() void ModbusTCPServerSlot::terminate()
{ {
try try
{ {
ModbusTCPServer::terminate(); ModbusTCPServer::terminate();
} }
catch( std::exception& ex ) {} catch( std::exception& ex ) {}
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -29,567 +29,567 @@ ...@@ -29,567 +29,567 @@
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
namespace uniset namespace uniset
{ {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
using namespace std; using namespace std;
using namespace ModbusRTU; using namespace ModbusRTU;
using namespace uniset; using namespace uniset;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPSession::~ModbusTCPSession() ModbusTCPSession::~ModbusTCPSession()
{ {
cancelled = true; cancelled = true;
if( io.is_active() ) if( io.is_active() )
io.stop(); io.stop();
if( ioTimeout.is_active() ) if( ioTimeout.is_active() )
ioTimeout.stop(); ioTimeout.stop();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusTCPSession::ModbusTCPSession(const Poco::Net::StreamSocket& s, const std::unordered_set<ModbusAddr>& a, timeout_t timeout ): ModbusTCPSession::ModbusTCPSession(const Poco::Net::StreamSocket& s, const std::unordered_set<ModbusAddr>& a, timeout_t timeout ):
vaddr(a), vaddr(a),
timeout(timeout), timeout(timeout),
peername(""), peername(""),
caddr(""), caddr(""),
cancelled(false) cancelled(false)
{ {
try try
{ {
sock = make_shared<UTCPStream>(s); sock = make_shared<UTCPStream>(s);
// если стремиться к "оптимизации по скорости" // если стремиться к "оптимизации по скорости"
// то getpeername "медленная" операция и может стоит от неё отказаться. // то getpeername "медленная" операция и может стоит от неё отказаться.
Poco::Net::SocketAddress iaddr = sock->peerAddress(); Poco::Net::SocketAddress iaddr = sock->peerAddress();
if( iaddr.host().toString().empty() ) if( iaddr.host().toString().empty() )
{ {
ostringstream err; ostringstream err;
err << "(ModbusTCPSession): unknonwn ip(0.0.0.0) client disconnected?!"; err << "(ModbusTCPSession): unknonwn ip(0.0.0.0) client disconnected?!";
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << err.str() << endl; dlog->crit() << err.str() << endl;
sock.reset(); sock.reset();
throw SystemError(err.str()); throw SystemError(err.str());
} }
caddr = iaddr.host().toString(); caddr = iaddr.host().toString();
ostringstream s; ostringstream s;
s << caddr << ":" << iaddr.port(); s << caddr << ":" << iaddr.port();
peername = s.str(); peername = s.str();
} }
catch( const Poco::Net::NetException& ex ) catch( const Poco::Net::NetException& ex )
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << "(ModbusTCPSession): err: " << ex.displayText() << endl; dlog->crit() << "(ModbusTCPSession): err: " << ex.displayText() << endl;
sock.reset(); sock.reset();
throw SystemError(ex.message()); throw SystemError(ex.message());
} }
sock->setBlocking(false); // fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) | O_NONBLOCK); sock->setBlocking(false); // fcntl(sfd, F_SETFL, fcntl(sfd, F_GETFL, 0) | O_NONBLOCK);
setCRCNoCheckit(true); setCRCNoCheckit(true);
timeout_t tout = timeout / 1000; timeout_t tout = timeout / 1000;
if( tout <= 0 ) if( tout <= 0 )
tout = 3; tout = 3;
io.set<ModbusTCPSession, &ModbusTCPSession::callback>(this); io.set<ModbusTCPSession, &ModbusTCPSession::callback>(this);
ioTimeout.set<ModbusTCPSession, &ModbusTCPSession::onTimeout>(this); ioTimeout.set<ModbusTCPSession, &ModbusTCPSession::onTimeout>(this);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::setSessionTimeout( double t ) void ModbusTCPSession::setSessionTimeout( double t )
{ {
sessTimeout = t; sessTimeout = t;
if( t <= 0 ) if( t <= 0 )
ioTimeout.stop(); ioTimeout.stop();
else if( ioTimeout.is_active() ) else if( ioTimeout.is_active() )
ioTimeout.start(t); ioTimeout.start(t);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::iowait( timeout_t msec ) void ModbusTCPSession::iowait( timeout_t msec )
{ {
ptWait.setTiming(msec); ptWait.setTiming(msec);
while( !ptWait.checkTime() ) while( !ptWait.checkTime() )
io.loop.iteration(); io.loop.iteration();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::run( ev::loop_ref& loop ) void ModbusTCPSession::run( ev::loop_ref& loop )
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << peername << "(run): run session.." << endl; dlog->info() << peername << "(run): run session.." << endl;
io.set(loop); io.set(loop);
io.start(sock->getSocket(), ev::READ); io.start(sock->getSocket(), ev::READ);
ioTimeout.set(loop); ioTimeout.set(loop);
if( sessTimeout > 0 ) if( sessTimeout > 0 )
ioTimeout.start(sessTimeout); ioTimeout.start(sessTimeout);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool ModbusTCPSession::isActive() const bool ModbusTCPSession::isActive() const
{ {
return io.is_active(); return io.is_active();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::callback( ev::io& watcher, int revents ) void ModbusTCPSession::callback( ev::io& watcher, int revents )
{ {
if( EV_ERROR & revents ) if( EV_ERROR & revents )
{ {
if( dlog->is_crit() ) if( dlog->is_crit() )
dlog->crit() << peername << "(callback): EVENT ERROR.." << endl; dlog->crit() << peername << "(callback): EVENT ERROR.." << endl;
return; return;
} }
if (revents & EV_READ) if (revents & EV_READ)
readEvent(watcher); readEvent(watcher);
if (revents & EV_WRITE) if (revents & EV_WRITE)
writeEvent(watcher); writeEvent(watcher);
if( qsend.empty() ) if( qsend.empty() )
io.set(ev::READ); io.set(ev::READ);
else else
io.set(ev::READ | ev::WRITE); io.set(ev::READ | ev::WRITE);
if( cancelled ) if( cancelled )
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << peername << ": stop session... disconnect.." << endl; dlog->info() << peername << ": stop session... disconnect.." << endl;
terminate(); terminate();
} }
else if( sessTimeout > 0 ) else if( sessTimeout > 0 )
ioTimeout.start(sessTimeout); // restart timer.. ioTimeout.start(sessTimeout); // restart timer..
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::onTimeout( ev::timer& t, int revents ) void ModbusTCPSession::onTimeout( ev::timer& t, int revents )
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << peername << ": timeout connection activity..(terminate session)" << endl; dlog->info() << peername << ": timeout connection activity..(terminate session)" << endl;
t.stop(); t.stop();
terminate(); terminate();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::readEvent( ev::io& watcher ) void ModbusTCPSession::readEvent( ev::io& watcher )
{ {
if( receive(vaddr, timeout) == erSessionClosed ) if( receive(vaddr, timeout) == erSessionClosed )
cancelled = true; cancelled = true;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::writeEvent( ev::io& watcher ) void ModbusTCPSession::writeEvent( ev::io& watcher )
{ {
if( qsend.empty() ) if( qsend.empty() )
return; return;
UTCPCore::Buffer* buffer = qsend.front(); UTCPCore::Buffer* buffer = qsend.front();
ssize_t ret = write(watcher.fd, buffer->dpos(), buffer->nbytes()); ssize_t ret = write(watcher.fd, buffer->dpos(), buffer->nbytes());
if( ret < 0 ) if( ret < 0 )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << peername << "(writeEvent): write to socket error: " << strerror(errno) << endl; dlog->warn() << peername << "(writeEvent): write to socket error: " << strerror(errno) << endl;
return; return;
} }
buffer->pos += ret; buffer->pos += ret;
if( buffer->nbytes() == 0 ) if( buffer->nbytes() == 0 )
{ {
qsend.pop(); qsend.pop();
delete buffer; delete buffer;
} }
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPSession::realReceive( const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t msec ) ModbusRTU::mbErrCode ModbusTCPSession::realReceive( const std::unordered_set<ModbusAddr>& vmbaddr, timeout_t msec )
{ {
ModbusRTU::mbErrCode res = erTimeOut; ModbusRTU::mbErrCode res = erTimeOut;
ptTimeout.setTiming(msec); ptTimeout.setTiming(msec);
try try
{ {
buf.clear(); buf.clear();
res = tcp_processing(buf.mbaphead); res = tcp_processing(buf.mbaphead);
if( res != erNoError ) if( res != erNoError )
return res; return res;
if( msec != UniSetTimer::WaitUpTime ) if( msec != UniSetTimer::WaitUpTime )
{ {
msec = ptTimeout.getLeft(msec); msec = ptTimeout.getLeft(msec);
if( msec == 0 ) // времени для ответа не осталось.. if( msec == 0 ) // времени для ответа не осталось..
return erTimeOut; return erTimeOut;
} }
if( qrecv.empty() ) if( qrecv.empty() )
return erTimeOut; return erTimeOut;
if( cancelled ) if( cancelled )
return erSessionClosed; return erSessionClosed;
// запоминаем принятый заголовок, // запоминаем принятый заголовок,
// для формирования ответа (см. make_adu_header) // для формирования ответа (см. make_adu_header)
curQueryHeader = buf.mbaphead; curQueryHeader = buf.mbaphead;
if( dlog->is_level9() ) if( dlog->is_level9() )
dlog->level9() << "(ModbusTCPSession::recv): ADU len=" << curQueryHeader.len << endl; dlog->level9() << "(ModbusTCPSession::recv): ADU len=" << curQueryHeader.len << endl;
res = recv( vmbaddr, buf, msec ); res = recv( vmbaddr, buf, msec );
if( cancelled ) if( cancelled )
return erSessionClosed; return erSessionClosed;
if( res != erNoError ) // && res!=erBadReplyNodeAddress ) if( res != erNoError ) // && res!=erBadReplyNodeAddress )
{ {
if( res < erInternalErrorCode ) if( res < erInternalErrorCode )
{ {
ErrorRetMessage em( buf.addr(), buf.func(), res ); ErrorRetMessage em( buf.addr(), buf.func(), res );
buf = em.transport_msg(); buf = em.transport_msg();
send(buf); send(buf);
printProcessingTime(); printProcessingTime();
} }
else if( aftersend_msec > 0 ) else if( aftersend_msec > 0 )
iowait(aftersend_msec); iowait(aftersend_msec);
return res; return res;
} }
if( msec != UniSetTimer::WaitUpTime ) if( msec != UniSetTimer::WaitUpTime )
{ {
msec = ptTimeout.getLeft(msec); msec = ptTimeout.getLeft(msec);
if( msec == 0 ) if( msec == 0 )
return erTimeOut; return erTimeOut;
} }
if( cancelled ) if( cancelled )
return erSessionClosed; return erSessionClosed;
// processing message... // processing message...
res = processing(buf); res = processing(buf);
} }
catch( uniset::CommFailed& ex ) catch( uniset::CommFailed& ex )
{ {
cancelled = true; cancelled = true;
return erSessionClosed; return erSessionClosed;
} }
return res; return res;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::final() void ModbusTCPSession::final()
{ {
slFin(this); slFin(this);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::sendData( unsigned char* buf, int len ) mbErrCode ModbusTCPSession::sendData( unsigned char* buf, int len )
{ {
qsend.emplace( new UTCPCore::Buffer(buf, len) ); qsend.emplace( new UTCPCore::Buffer(buf, len) );
return erNoError; return erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
size_t ModbusTCPSession::getNextData( unsigned char* buf, int len ) size_t ModbusTCPSession::getNextData( unsigned char* buf, int len )
{ {
ssize_t res = ModbusTCPCore::getDataFD( sock->getSocket(), qrecv, buf, len ); ssize_t res = ModbusTCPCore::getDataFD( sock->getSocket(), qrecv, buf, len );
try try
{ {
if( res > 0 ) if( res > 0 )
return res; return res;
if( res < 0 ) if( res < 0 )
{ {
int errnum = errno; int errnum = errno;
if( errnum != EAGAIN && dlog->is_warn() ) if( errnum != EAGAIN && dlog->is_warn() )
dlog->warn() << peername << "(getNextData): read from socket error(" << errnum << "): " << strerror(errnum) << endl; dlog->warn() << peername << "(getNextData): read from socket error(" << errnum << "): " << strerror(errnum) << endl;
return 0; return 0;
} }
} }
catch( const uniset::CommFailed& ex ){} catch( const uniset::CommFailed& ex ) {}
if( !cancelled && dlog->is_info() ) if( !cancelled && dlog->is_info() )
dlog->info() << peername << "(getNextData): client disconnected" << endl; dlog->info() << peername << "(getNextData): client disconnected" << endl;
cancelled = true; cancelled = true;
return 0; return 0;
} }
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
mbErrCode ModbusTCPSession::tcp_processing( ModbusRTU::MBAPHeader& mhead ) mbErrCode ModbusTCPSession::tcp_processing( ModbusRTU::MBAPHeader& mhead )
{ {
// чистим очередь // чистим очередь
while( !qrecv.empty() ) while( !qrecv.empty() )
qrecv.pop(); qrecv.pop();
size_t len = getNextData((unsigned char*)(&mhead), sizeof(mhead)); size_t len = getNextData((unsigned char*)(&mhead), sizeof(mhead));
//size_t len = ModbusTCPCore::getDataFD( sfd, qrecv, (unsigned char*)(&mhead), sizeof(mhead) ); //size_t len = ModbusTCPCore::getDataFD( sfd, qrecv, (unsigned char*)(&mhead), sizeof(mhead) );
if( len < sizeof(mhead) ) if( len < sizeof(mhead) )
{ {
if( len == 0 ) if( len == 0 )
return erSessionClosed; return erSessionClosed;
return erInvalidFormat; return erInvalidFormat;
} }
mhead.swapdata(); mhead.swapdata();
if( dlog->is_level9() ) if( dlog->is_level9() )
{ {
dlog->level9() << peername << "(tcp_processing): recv tcp header(" << len << "): "; dlog->level9() << peername << "(tcp_processing): recv tcp header(" << len << "): ";
mbPrintMessage( dlog->level9(false), (ModbusByte*)(&mhead), sizeof(mhead)); mbPrintMessage( dlog->level9(false), (ModbusByte*)(&mhead), sizeof(mhead));
dlog->level9(false) << endl; dlog->level9(false) << endl;
} }
// check header // check header
if( mhead.pID != 0 ) if( mhead.pID != 0 )
return erUnExpectedPacketType; // erTimeOut; return erUnExpectedPacketType; // erTimeOut;
if( mhead.len == 0 ) if( mhead.len == 0 )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(ModbusTCPServer::tcp_processing): BAD FORMAT: len=0!" << endl; dlog->warn() << "(ModbusTCPServer::tcp_processing): BAD FORMAT: len=0!" << endl;
return erInvalidFormat; return erInvalidFormat;
} }
if( mhead.len > ModbusRTU::MAXLENPACKET ) if( mhead.len > ModbusRTU::MAXLENPACKET )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << "(ModbusTCPServer::tcp_processing): len(" << (int)mhead.len dlog->warn() << "(ModbusTCPServer::tcp_processing): len(" << (int)mhead.len
<< ") < MAXLENPACKET(" << ModbusRTU::MAXLENPACKET << ")" << endl; << ") < MAXLENPACKET(" << ModbusRTU::MAXLENPACKET << ")" << endl;
return erInvalidFormat; return erInvalidFormat;
} }
pt.setTiming(10); pt.setTiming(10);
try try
{ {
do do
{ {
len = ModbusTCPCore::readDataFD( sock->getSocket(), qrecv, mhead.len ); len = ModbusTCPCore::readDataFD( sock->getSocket(), qrecv, mhead.len );
if( len == 0 ) if( len == 0 )
io.loop.iteration(); io.loop.iteration();
} }
while( len == 0 && !pt.checkTime() ); while( len == 0 && !pt.checkTime() );
} }
catch( const uniset::CommFailed& ex ){} catch( const uniset::CommFailed& ex ) {}
if( len < mhead.len ) if( len < mhead.len )
{ {
if( dlog->is_warn() ) if( dlog->is_warn() )
dlog->warn() << peername << "(tcp_processing): len(" << (int)len dlog->warn() << peername << "(tcp_processing): len(" << (int)len
<< ") < mhead.len(" << (int)mhead.len << ")" << endl; << ") < mhead.len(" << (int)mhead.len << ")" << endl;
return erInvalidFormat; return erInvalidFormat;
} }
return erNoError; return erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPSession::post_send_request( ModbusRTU::ModbusMessage& request ) ModbusRTU::mbErrCode ModbusTCPSession::post_send_request( ModbusRTU::ModbusMessage& request )
{ {
return erNoError; return erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::make_adu_header( ModbusMessage& req ) mbErrCode ModbusTCPSession::make_adu_header( ModbusMessage& req )
{ {
req.makeMBAPHeader(curQueryHeader.tID, isCRCNoCheckit(), curQueryHeader.pID); req.makeMBAPHeader(curQueryHeader.tID, isCRCNoCheckit(), curQueryHeader.pID);
return erNoError; return erNoError;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::cleanInputStream() void ModbusTCPSession::cleanInputStream()
{ {
unsigned char tmpbuf[100]; unsigned char tmpbuf[100];
size_t ret = 0; size_t ret = 0;
do do
{ {
ret = getNextData(tmpbuf, sizeof(tmpbuf)); ret = getNextData(tmpbuf, sizeof(tmpbuf));
} }
while( ret > 0); while( ret > 0);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::cleanupChannel() void ModbusTCPSession::cleanupChannel()
{ {
cleanInputStream(); cleanInputStream();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::terminate() void ModbusTCPSession::terminate()
{ {
if( dlog->is_info() ) if( dlog->is_info() )
dlog->info() << peername << "(terminate)..." << endl; dlog->info() << peername << "(terminate)..." << endl;
cancelled = true; cancelled = true;
io.stop(); io.stop();
ioTimeout.stop(); ioTimeout.stop();
ModbusServer::terminate(); ModbusServer::terminate();
sock.reset(); // close.. sock.reset(); // close..
final(); // после этого вызова возможно данный объект будет разрушен! final(); // после этого вызова возможно данный объект будет разрушен!
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::readCoilStatus( ReadCoilMessage& query, mbErrCode ModbusTCPSession::readCoilStatus( ReadCoilMessage& query,
ReadCoilRetMessage& reply ) ReadCoilRetMessage& reply )
{ {
if( !slReadCoil ) if( !slReadCoil )
return erOperationFailed; return erOperationFailed;
return slReadCoil(query, reply); return slReadCoil(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::readInputStatus( ReadInputStatusMessage& query, mbErrCode ModbusTCPSession::readInputStatus( ReadInputStatusMessage& query,
ReadInputStatusRetMessage& reply ) ReadInputStatusRetMessage& reply )
{ {
if( !slReadInputStatus ) if( !slReadInputStatus )
return erOperationFailed; return erOperationFailed;
return slReadInputStatus(query, reply); return slReadInputStatus(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::readOutputRegisters( ReadOutputMessage& query, mbErrCode ModbusTCPSession::readOutputRegisters( ReadOutputMessage& query,
ReadOutputRetMessage& reply ) ReadOutputRetMessage& reply )
{ {
if( !slReadOutputs ) if( !slReadOutputs )
return erOperationFailed; return erOperationFailed;
return slReadOutputs(query, reply); return slReadOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::readInputRegisters( ReadInputMessage& query, mbErrCode ModbusTCPSession::readInputRegisters( ReadInputMessage& query,
ReadInputRetMessage& reply ) ReadInputRetMessage& reply )
{ {
if( !slReadInputs ) if( !slReadInputs )
return erOperationFailed; return erOperationFailed;
return slReadInputs(query, reply); return slReadInputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::forceMultipleCoils( ForceCoilsMessage& query, mbErrCode ModbusTCPSession::forceMultipleCoils( ForceCoilsMessage& query,
ForceCoilsRetMessage& reply ) ForceCoilsRetMessage& reply )
{ {
if( !slForceCoils ) if( !slForceCoils )
return erOperationFailed; return erOperationFailed;
return slForceCoils(query, reply); return slForceCoils(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::writeOutputRegisters( WriteOutputMessage& query, mbErrCode ModbusTCPSession::writeOutputRegisters( WriteOutputMessage& query,
WriteOutputRetMessage& reply ) WriteOutputRetMessage& reply )
{ {
if( !slWriteOutputs ) if( !slWriteOutputs )
return erOperationFailed; return erOperationFailed;
return slWriteOutputs(query, reply); return slWriteOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::diagnostics( DiagnosticMessage& query, mbErrCode ModbusTCPSession::diagnostics( DiagnosticMessage& query,
DiagnosticRetMessage& reply ) DiagnosticRetMessage& reply )
{ {
if( !slDiagnostics ) if( !slDiagnostics )
return erOperationFailed; return erOperationFailed;
return slDiagnostics(query, reply); return slDiagnostics(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPSession::read4314( ModbusRTU::MEIMessageRDI& query, ModbusRTU::mbErrCode ModbusTCPSession::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply ) ModbusRTU::MEIMessageRetRDI& reply )
{ {
if( !slMEIRDI ) if( !slMEIRDI )
return erOperationFailed; return erOperationFailed;
return slMEIRDI(query, reply); return slMEIRDI(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::forceSingleCoil( ForceSingleCoilMessage& query, mbErrCode ModbusTCPSession::forceSingleCoil( ForceSingleCoilMessage& query,
ForceSingleCoilRetMessage& reply ) ForceSingleCoilRetMessage& reply )
{ {
if( !slForceSingleCoil ) if( !slForceSingleCoil )
return erOperationFailed; return erOperationFailed;
return slForceSingleCoil(query, reply); return slForceSingleCoil(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::writeOutputSingleRegister( WriteSingleOutputMessage& query, mbErrCode ModbusTCPSession::writeOutputSingleRegister( WriteSingleOutputMessage& query,
WriteSingleOutputRetMessage& reply ) WriteSingleOutputRetMessage& reply )
{ {
if( !slWriteSingleOutputs ) if( !slWriteSingleOutputs )
return erOperationFailed; return erOperationFailed;
return slWriteSingleOutputs(query, reply); return slWriteSingleOutputs(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
mbErrCode ModbusTCPSession::journalCommand( JournalCommandMessage& query, mbErrCode ModbusTCPSession::journalCommand( JournalCommandMessage& query,
JournalCommandRetMessage& reply ) JournalCommandRetMessage& reply )
{ {
if( !slJournalCommand ) if( !slJournalCommand )
return erOperationFailed; return erOperationFailed;
return slJournalCommand(query, reply); return slJournalCommand(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPSession::setDateTime( ModbusRTU::SetDateTimeMessage& query, ModbusRTU::mbErrCode ModbusTCPSession::setDateTime( ModbusRTU::SetDateTimeMessage& query,
ModbusRTU::SetDateTimeRetMessage& reply ) ModbusRTU::SetDateTimeRetMessage& reply )
{ {
if( !slSetDateTime ) if( !slSetDateTime )
return erOperationFailed; return erOperationFailed;
return slSetDateTime(query, reply); return slSetDateTime(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPSession::remoteService( ModbusRTU::RemoteServiceMessage& query, ModbusRTU::mbErrCode ModbusTCPSession::remoteService( ModbusRTU::RemoteServiceMessage& query,
ModbusRTU::RemoteServiceRetMessage& reply ) ModbusRTU::RemoteServiceRetMessage& reply )
{ {
if( !slRemoteService ) if( !slRemoteService )
return erOperationFailed; return erOperationFailed;
return slRemoteService(query, reply); return slRemoteService(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ModbusRTU::mbErrCode ModbusTCPSession::fileTransfer( ModbusRTU::FileTransferMessage& query, ModbusRTU::mbErrCode ModbusTCPSession::fileTransfer( ModbusRTU::FileTransferMessage& query,
ModbusRTU::FileTransferRetMessage& reply ) ModbusRTU::FileTransferRetMessage& reply )
{ {
if( !slFileTransfer ) if( !slFileTransfer )
return erOperationFailed; return erOperationFailed;
return slFileTransfer(query, reply); return slFileTransfer(query, reply);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::setChannelTimeout( timeout_t msec ) void ModbusTCPSession::setChannelTimeout( timeout_t msec )
{ {
setSessionTimeout(msec); setSessionTimeout(msec);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void ModbusTCPSession::connectFinalSession( FinalSlot sl ) void ModbusTCPSession::connectFinalSession( FinalSlot sl )
{ {
slFin = sl; slFin = sl;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
string ModbusTCPSession::getClientAddress() const string ModbusTCPSession::getClientAddress() const
{ {
return caddr; return caddr;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
This source diff could not be displayed because it is too large. You can view the blob instead.
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