Commit 1dbfb9f1 authored by Pavel Vaynerman's avatar Pavel Vaynerman

fixed bug in ModbusRTU::ForceMultipleCoils function

parent f47ec246
......@@ -17,7 +17,7 @@ MBSlave::MBSlave( ModbusRTU::ModbusAddr addr, const std::string dev, const std::
// prev(ModbusRTU::erNoError),
// askCount(0),
verbose(false),
replyVal(0)
replyVal(-1)
{
cout << "$Id: MBSlave.cc,v 1.7 2009/02/24 20:27:24 vpashka Exp $" << endl;
......@@ -80,7 +80,7 @@ void MBSlave::execute()
{
//
askCount = askCount>=numeric_limits<long>::max() ? 0 : askCount+1;
if( res!=ModbusRTU::erNoError )
if( res!=ModbusRTU::erNoError )
errmap[res]++;
prev = res;
......@@ -115,7 +115,7 @@ ModbusRTU::mbErrCode MBSlave::readCoilStatus( ReadCoilMessage& query,
for( int i=0; i<bcnt; i++ )
{
if( replyVal )
if( replyVal!=-1 )
reply.addData(replyVal);
else
reply.addData(d);
......@@ -141,7 +141,7 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query,
for( int i=0; i<bcnt; i++ )
{
if( replyVal )
if( replyVal!=-1 )
reply.addData(replyVal);
else
reply.addData(d);
......@@ -158,10 +158,10 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query,
if( query.count <= 1 )
{
if( replyVal )
if( replyVal!=-1 )
reply.addData(replyVal);
else
reply.addData(query.start);
reply.addData(query.start);
return ModbusRTU::erNoError;
}
......@@ -170,7 +170,7 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query,
ModbusData reg = query.start;
for( ; num<query.count; num++, reg++ )
{
if( replyVal )
if( replyVal != -1 )
reply.addData(replyVal);
else
reply.addData(reg);
......@@ -195,7 +195,7 @@ ModbusRTU::mbErrCode MBSlave::readOutputRegisters(
if( query.count <= 1 )
{
if( replyVal )
if( replyVal != -1 )
reply.addData(replyVal);
else
reply.addData(query.start);
......@@ -207,7 +207,7 @@ ModbusRTU::mbErrCode MBSlave::readOutputRegisters(
ModbusData reg = query.start;
for( ; num<query.count; num++, reg++ )
{
if( replyVal )
if( replyVal != -1 )
reply.addData(replyVal);
else
reply.addData(reg);
......
......@@ -44,7 +44,7 @@ int main( int argc, char **argv )
int tout = 2000;
DebugStream dlog;
int use485 = 0;
int replyVal=0;
int replyVal=-1;
try
{
......@@ -104,7 +104,8 @@ int main( int argc, char **argv )
MBSlave mbs(myaddr,dev,speed,use485);
mbs.setLog(dlog);
mbs.setVerbose(verb);
mbs.setReply(replyVal);
if( replyVal!=-1 )
mbs.setReply(replyVal);
mbs.execute();
}
catch( ModbusRTU::mbException& ex )
......
......@@ -458,7 +458,7 @@ int main( int argc, char **argv )
}
ModbusRTU::ForceCoilsMessage msg(slaveaddr,reg);
ModbusRTU::DataBits16 b(val);
ModbusRTU::DataBits b(val);
msg.addData(b);
ModbusRTU::ForceCoilsRetMessage ret = mb.write0F(msg);
if( verb )
......
......@@ -338,7 +338,7 @@ int main( int argc, char **argv )
}
ModbusRTU::ForceCoilsMessage msg(slaveaddr,reg);
ModbusRTU::DataBits16 b(val);
ModbusRTU::DataBits b(val);
msg.addData(b);
ModbusRTU::ForceCoilsRetMessage ret = mb.write0F(msg);
if( verb )
......
......@@ -50,7 +50,7 @@
<RSExchange name="RSExchange">
<RespondList>
<item addr="0x02" respondSensor="RTU_Not_Respond_FS" timeout="5000" invert="1" default="1"/>
<item addr="0x02" respondSensor="RTU_Not_Respond_FS" timeout="2000" invert="1" default="1"/>
</RespondList>
</RSExchange>
</settings>
......@@ -108,7 +108,7 @@
<item id="5" name="HC_in" textname="HC_in"
iotype="DI" character="Info"
rs="2" mbtype="rtu" mbaddr="0x02" mbreg="0x302" mbfunc="0x05">
rs="3" mbtype="rtu" mbaddr="0x02" mbreg="0x302" mbfunc="0x04" vtype="F2">
<consumers>
</consumers>
</item>
......
......@@ -19,7 +19,8 @@ force_out(false),
mbregFromID(false),
activated(false),
rs_pre_clean(false),
noQueryOptimization(false)
noQueryOptimization(false),
allNotRespond(false)
{
cout << "$Id: RTUExchange.cc,v 1.4 2009/01/23 23:56:54 vpashka Exp $" << endl;
......@@ -53,7 +54,13 @@ noQueryOptimization(false)
recv_timeout = atoi(conf->getArgParam("--rs-recv-timeout",it.getProp("recv_timeout")).c_str());
if( recv_timeout <= 0 )
recv_timeout = 100;
recv_timeout = 50;
int alltout = atoi(conf->getArgParam("--rs-all-timeout",it.getProp("all_timeout")).c_str());
if( alltout <=0 )
alltout = 2000;
ptAllNotRespond.setTiming(alltout);
rs_pre_clean = atoi(conf->getArgParam("--rs-pre-clean",it.getProp("pre_clean")).c_str());
noQueryOptimization = atoi(conf->getArgParam("--rs-no-query-optimization",it.getProp("no_query_optimization")).c_str());
......@@ -76,6 +83,7 @@ noQueryOptimization(false)
{
readConfiguration();
rtuQueryOptimization(rmap);
initRespondList();
}
else
ic->addReadItem( sigc::mem_fun(this,&RTUExchange::readItem) );
......@@ -122,7 +130,7 @@ noQueryOptimization(false)
if( activateTimeout<=0 )
activateTimeout = 20000;
initMB();
initMB(false);
printMap(rmap);
// abort();
......@@ -149,18 +157,27 @@ RTUExchange::~RTUExchange()
delete shm;
}
// -----------------------------------------------------------------------------
void RTUExchange::initMB()
void RTUExchange::initMB( bool reopen )
{
if( !file_exist(devname) )
{
if( mb )
{
delete mb;
mb=0;
mb = 0;
}
return;
}
if( mb )
{
if( !reopen )
return;
delete mb;
mb = 0;
}
try
{
mb = new ModbusRTUMaster(devname);
......@@ -235,9 +252,18 @@ void RTUExchange::step()
// -----------------------------------------------------------------------------
void RTUExchange::poll()
{
if( trAllNotRespond.hi(allNotRespond) )
ptAllNotRespond.reset();
if( allNotRespond && mb && ptAllNotRespond.checkTime() )
{
ptAllNotRespond.reset();
initMB(true);
}
if( !mb )
{
initMB();
initMB(false);
if( !mb )
{
for( RTUExchange::RTUDeviceMap::iterator it=rmap.begin(); it!=rmap.end(); ++it )
......@@ -286,6 +312,7 @@ void RTUExchange::poll()
}
else
{
d->resp_real = false;
for( RTUExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
try
......@@ -303,8 +330,9 @@ void RTUExchange::poll()
if( d->resp_real )
{
dlog[Debug::CRIT] << myname << "(poll): FAILED ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< "reg=" << ModbusRTU::dat2str(it->second->mbreg)
<< " -> " << ex << endl;
d->resp_real = false;
// d->resp_real = false;
}
}
......@@ -383,11 +411,7 @@ bool RTUExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
{
ModbusRTU::DataBits b(ret.data[i]);
for( int k=0;k<ModbusRTU::BitsPerByte && m<p->q_count; k++,it++,m++ )
{
// cerr << "(read02): save mbreg=" << ModbusRTU::dat2str(it->second->mbreg)
// << " val=" << (int)(b[k]) << endl;
it->second->mbval = b[k];
}
}
it--;
}
......@@ -401,11 +425,7 @@ bool RTUExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
{
ModbusRTU::DataBits b(ret.data[i]);
for( int k=0;k<ModbusRTU::BitsPerByte && m<p->q_count; k++,it++,m++ )
{
// cerr << "(read01): save mbreg=" << ModbusRTU::dat2str(it->second->mbreg)
// << " val=" << (int)(b[k]) << endl;
it->second->mbval = b[k] ? 1 : 0;
}
}
it--;
}
......@@ -449,14 +469,8 @@ bool RTUExchange::pollRTU( RTUDevice* dev, RegMap::iterator& it )
case ModbusRTU::fnForceMultipleCoils:
{
ModbusRTU::ForceCoilsMessage msg(dev->mbaddr,p->mbreg+p->offset);
for( int i=0; i<p->q_count; i++ )
{
ModbusRTU::DataBits16 d;
for( int k=0; k<ModbusRTU::BitsPerData && i<p->q_count; k++,i++,it++ )
d.set(k, (it->second->mbval ? true : false) );
msg.addData(d);
}
for( int i=0; i<p->q_count; i++,it++ )
msg.addBit( it->second->mbval ? true : false );
it--;
ModbusRTU::ForceCoilsRetMessage ret = mb->write0F(msg);
......@@ -495,16 +509,20 @@ bool RTUExchange::RTUDevice::checkRespond()
// -----------------------------------------------------------------------------
void RTUExchange::updateSM()
{
allNotRespond = true;
for( RTUExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
/*
cout << "check respond addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " respond=" << d->resp_id
<< " real=" << d->resp_real
<< " state=" << d->resp_state
<< endl;
*/
if( d->resp_real )
allNotRespond = false;
// update respond sensors......
if( d->checkRespond() && d->resp_id != DefaultObjectId )
{
......@@ -520,6 +538,8 @@ void RTUExchange::updateSM()
}
}
cerr << "*********** allNotRespond=" << allNotRespond << endl;
// update values...
for( RTUExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
......@@ -1483,9 +1503,18 @@ bool RTUExchange::initRespondInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, Uni
d->second->resp_ptTimeout.setTiming(UniSetTimer::WaitUpTime);
d->second->resp_invert = atoi(it.getProp("invert").c_str());
d->second->resp_state = UniSetTypes::uni_atoi(it.getProp("default").c_str());
d->second->resp_real = UniSetTypes::uni_atoi(it.getProp("default").c_str());
d->second->resp_trTimeout.change(d->second->resp_real);
/*
if( !it.getProp("default").empty() )
{
d->second->resp_state = UniSetTypes::uni_atoi(it.getProp("default").c_str());
d->second->resp_real = UniSetTypes::uni_atoi(it.getProp("default").c_str());
}
*/
/*
d->second->resp_real = true;
d->second->resp_state = false;
d->second->resp_trTimeout.change(false);
*/
return true;
}
// -----------------------------------------------------------------------------
......@@ -1515,10 +1544,10 @@ std::ostream& operator<<( std::ostream& os, RTUExchange::RTUDevice& d )
os << " rtu=" << (d.rtu ? "yes" : "no" );
os << " repond_id=" << d.resp_id
<< " repond_timeout=" << d.resp_ptTimeout.getInterval()
<< " repond_state=" << d.resp_state
<< " repond_invert=" << d.resp_invert
os << " respond_id=" << d.resp_id
<< " respond_timeout=" << d.resp_ptTimeout.getInterval()
<< " respond_state=" << d.resp_state
<< " respond_invert=" << d.resp_invert
<< endl;
......@@ -1613,14 +1642,6 @@ void RTUExchange::rtuQueryOptimization( RTUDeviceMap& m )
void RTUExchange::updateRTU( RegMap::iterator& rit )
{
RegInfo* r(rit->second);
using namespace ModbusRTU;
bool save = isWriteFunction( r->mbfunc );
// if( !force_out_up && save )
// return;
ModbusRTU::DataBits16 b(r->mbval);
for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it )
updateRSProperty( &(*it),false );
}
......
......@@ -123,11 +123,13 @@ class RTUExchange:
mbaddr(0),
dtype(dtUnknown),
resp_id(UniSetTypes::DefaultObjectId),
resp_state(true),
resp_state(false),
resp_invert(false),
resp_real(false),
resp_real(true),
rtu(0)
{}
{
resp_trTimeout.change(false);
}
bool respnond;
ModbusRTU::ModbusAddr mbaddr; /*!< */
......@@ -196,7 +198,7 @@ class RTUExchange:
//
virtual void sigterm( int signo );
void initMB();
void initMB( bool reopen=false );
void initIterators();
bool initItem( UniXML_iterator& it );
bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
......@@ -244,6 +246,10 @@ class RTUExchange:
bool rs_pre_clean;
bool noQueryOptimization;
bool allNotRespond;
Trigger trAllNotRespond;
PassiveTimer ptAllNotRespond;
};
// -----------------------------------------------------------------------------
#endif // _RS_EXCHANGE_H_
......
......@@ -5,7 +5,7 @@ uniset-start.sh -f ./uniset-rtuexchange --confile test.xml \
--rs-name RSExchange \
--rs-speed 38400 \
--rs-filter-field rs \
--rs-filter-value 2 \
--rs-filter-value 1 \
--dlog-add-levels info,crit,warn \
--rs-force 0 \
--rs-force-out 0 \
......
......@@ -539,10 +539,10 @@ namespace ModbusRTU
public ModbusHeader
{
ModbusData start; /*!< */
ModbusData quant; /*!< */
ModbusData quant; /*!< */
ModbusByte bcnt; /*!< */
/*! */
ModbusData data[MAXLENPACKET/sizeof(ModbusData)-sizeof(ModbusData)*2-sizeof(ModbusByte)];
ModbusByte data[MAXLENPACKET-sizeof(ModbusData)*2-sizeof(ModbusByte)];
ModbusCRC crc; /*!< */
// ------- to slave -------
......@@ -554,16 +554,15 @@ namespace ModbusRTU
* \return TRUE -
* \return FALSE -
*/
bool addData( DataBits16 d );
/*! .
* \param dnum -
* \param bnum -
* \param state -
* \return TRUE -
* \return FALSE -
*/
bool setBit( unsigned char dnum, unsigned char bnum, bool state );
bool addData( DataBits d );
// return number of bit
// -1 - error
int addBit( bool state );
bool setBit( int nbit, bool state );
inline int last(){ return quant; }
/*! .
* \param dnum -
......@@ -571,12 +570,14 @@ namespace ModbusRTU
* \return TRUE -
* \return FALSE -
*/
bool getData( unsigned char dnum, DataBits16& d );
bool getData( unsigned char dnum, DataBits& d );
bool getBit( unsigned char bnum );
void clear();
inline bool isFull()
inline bool isFull()
{
return ( quant*sizeof(ModbusData) >= MAXLENPACKET );
return ( bcnt >= MAXLENPACKET );
}
// ------- from master -------
......
......@@ -1206,30 +1206,45 @@ ForceCoilsMessage::ForceCoilsMessage( ModbusAddr a, ModbusData s ):
func = fnForceMultipleCoils;
}
// -------------------------------------------------------------------------
bool ForceCoilsMessage::addData( DataBits16 d )
bool ForceCoilsMessage::addData( DataBits d )
{
if( isFull() )
return false;
data[quant++] = d.mdata();
bcnt = quant*sizeof(ModbusData);
data[bcnt++] = d.mbyte();
quant += BitsPerByte;
return true;
}
// -------------------------------------------------------------------------
bool ForceCoilsMessage::setBit( unsigned char dnum, unsigned char bnum, bool state )
int ForceCoilsMessage::addBit( bool state )
{
if( dnum<bcnt && bnum<BitsPerData )
{
DataBits16 d(data[dnum]);
d.b[bnum] = state;
data[dnum] = d;
return true;
}
int qnum = quant % BitsPerByte;
if( qnum == 0 )
bcnt++;
DataBits b(data[bcnt-1]);
b.b[qnum] = state;
data[bcnt-1] = b.mbyte();
quant++;
return (quant-1);
}
// -------------------------------------------------------------------------
bool ForceCoilsMessage::setBit( int nbit, bool state )
{
if( nbit<0 || nbit >= quant )
return false;
return false;
int bnum = nbit / BitsPerByte;
int qnum = nbit % BitsPerByte;
DataBits b(data[bnum]);
b.b[qnum] = state;
data[bnum] = b.mbyte();
return true;
}
// -------------------------------------------------------------------------
bool ForceCoilsMessage::getData( unsigned char dnum, DataBits16& d )
bool ForceCoilsMessage::getData( unsigned char dnum, DataBits& d )
{
if( dnum < bcnt )
{
......@@ -1270,14 +1285,8 @@ ModbusMessage ForceCoilsMessage::transport_msg()
memcpy(&(mm.data[ind]),&bcnt,sizeof(bcnt));
ind+=sizeof(bcnt);
// ,
ModbusData* dtmp = new ModbusData[quant];
for( int i=0; i<quant; i++ )
dtmp[i] = SWAPSHORT(data[i]);
//
memcpy(&(mm.data[ind]),dtmp,bcnt);
delete dtmp;
memcpy(&(mm.data[ind]),data,bcnt);
ind+=bcnt;
......@@ -1337,14 +1346,11 @@ void ForceCoilsMessage::init( ModbusMessage& m )
// CRC
memcpy(&crc,&(m.data[m.len-szCRC]),szCRC);
for( int i=0; i<quant; i++ )
data[i] = SWAPSHORT(data[i]);
}
// -------------------------------------------------------------------------
bool ForceCoilsMessage::checkFormat()
{
return ( (bcnt==(quant*sizeof(ModbusData))) && (func==fnForceMultipleCoils) );
return ( func==fnForceMultipleCoils );
}
// -------------------------------------------------------------------------
int ForceCoilsMessage::szData()
......@@ -1369,14 +1375,14 @@ std::ostream& ModbusRTU::operator<<(std::ostream& os, ForceCoilsMessage& m )
<< " bcnt=" << b2str(m.bcnt)
<< " data[" << (int)m.quant <<"]={ ";
for( int i=0; i<m.quant; i++ )
for( int i=0; i<m.bcnt; i++ )
{
DataBits16 d(m.data[i]);
DataBits d(m.data[i]);
os << "" << d << " ";
}
os << "}";
return os;
return os;
}
std::ostream& ModbusRTU::operator<<(std::ostream& os, ForceCoilsMessage* m )
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment