Commit aa746acf authored by Pavel Vainerman's avatar Pavel Vainerman

(MBTCPMaster): переписал систему начальной инициализации. Первый вариант.

parent af5fbfac
......@@ -269,6 +269,7 @@ void MBTCPMaster::poll()
it->second->resp_real = false;
}
updateSM();
allInitOK = false;
return;
}
......@@ -308,8 +309,12 @@ void MBTCPMaster::poll()
// }
// d->resp_real = false;
if( !d->ask_every_reg )
if( ex.err == ModbusRTU::erTimeOut && !d->ask_every_reg )
break;
// если контроллер хоть что-то ответил, то вроде как связь есть..
if( ex.err != ModbusRTU::erTimeOut )
d->resp_real = true;
}
if( it==d->regmap.end() )
......@@ -359,7 +364,9 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
<< " mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " mbfunc=" << p->mbfunc
<< " q_count=" << p->q_count
<< " mb_init=" << p->mb_init
<< " mb_initOK=" << p->mb_initOK
<< " sm_initOK=" << p->sm_initOK
<< " mbval=" << p->mbval
<< endl;
if( p->q_count > ModbusRTU::MAXDATALEN )
......@@ -437,8 +444,13 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
return false;
}
if( !p->mb_init )
if( !p->sm_initOK )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
// cerr << "**** mbreg=" << ModbusRTU::dat2str(p->mbreg) << " val=" << ModbusRTU::dat2str(p->mbval) << endl;
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(dev->mbaddr,p->mbreg,p->mbval);
......@@ -447,6 +459,14 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
case ModbusRTU::fnWriteOutputRegisters:
{
if( !p->sm_initOK )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
ModbusRTU::WriteOutputMessage msg(dev->mbaddr,p->mbreg);
for( int i=0; i<p->q_count; i++,it++ )
msg.addData(it->second->mbval);
......@@ -464,9 +484,13 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
<< " IGNORE FORCE SINGLE COIL (0x05) q_count=" << p->q_count << " ..." << endl;
return false;
}
if( !p->mb_init )
if( !p->sm_initOK )
{
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
// cerr << "****(coil) mbreg=" << ModbusRTU::dat2str(p->mbreg) << " val=" << ModbusRTU::dat2str(p->mbval) << endl;
ModbusRTU::ForceSingleCoilRetMessage ret = mb->write05(dev->mbaddr,p->mbreg,p->mbval);
......@@ -475,22 +499,14 @@ bool MBTCPMaster::pollRTU( RTUDevice* dev, RegMap::iterator& it )
case ModbusRTU::fnForceMultipleCoils:
{
#if 0
if( !p->mb_init )
{
// every register ask... (for mb_init_mbreg no some)
for( int i=0; i<p->q_count; i++,it++ )
if( !p->sm_initOK )
{
ModbusRTU::ReadInputStatusRetMessage ret1 = mb->read02(dev->mbaddr,it->second->mb_init_mbreg,1);
ModbusRTU::DataBits b(ret1.data[0]);
it->second->mbval = b[0] ? 1 : 0;
it->second->sm_init = true;
}
p->sm_init = true;
it--;
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << myname << "(pollRTU): mbreg=" << ModbusRTU::dat2str(p->mbreg)
<< " IGNORE...(sm_initOK=false)" << endl;
return true;
}
#endif
ModbusRTU::ForceCoilsMessage msg(dev->mbaddr,p->mbreg);
for( int i=0; i<p->q_count; i++,it++ )
msg.addBit( (it->second->mbval ? true : false) );
......@@ -520,9 +536,25 @@ void MBTCPMaster::firstInitRegisters()
allInitOK = true;
for( InitList::iterator it=initRegList.begin(); it!=initRegList.end(); ++it )
{
try
{
it->initOK = preInitRead( it );
allInitOK = it->initOK;
}
catch( ModbusRTU::mbException& ex )
{
allInitOK = false;
if( dlog.debugging(Debug::LEVEL3) )
{
dlog[Debug::LEVEL3] << myname << "(preInitRead): FAILED ask addr=" << ModbusRTU::addr2str(it->dev->mbaddr)
<< " reg=" << ModbusRTU::dat2str(it->mbreg)
<< " err: " << ex << endl;
}
if( !it->dev->ask_every_reg )
break;
}
}
}
// -----------------------------------------------------------------------------
bool MBTCPMaster::preInitRead( InitList::iterator& p )
......@@ -607,8 +639,13 @@ bool MBTCPMaster::preInitRead( InitList::iterator& p )
if( p->initOK )
{
p->ri->mb_init = true;
p->ri->sm_init = true;
p->ri->mb_initOK = true;
p->ri->sm_initOK = false;
bool f_out = force_out;
// выставляем флаг принудительного обновления
force_out = true;
updateRTU(p->ri->rit);
force_out = f_out;
}
return p->initOK;
......@@ -617,7 +654,6 @@ bool MBTCPMaster::preInitRead( InitList::iterator& p )
bool MBTCPMaster::initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p )
{
using namespace ModbusRTU;
try
{
if( p->vType == VTypes::vtUnknown )
......@@ -1065,14 +1101,14 @@ void MBTCPMaster::sensorInfo( UniSetTypes::SensorMessage* sm )
dlog[Debug::INFO] << myname<< "(sensorInfo): si.id=" << sm->id
<< " reg=" << ModbusRTU::dat2str(i->reg->mbreg)
<< " val=" << sm->value
<< " mb_init=" << i->reg->mb_init << endl;
<< " mb_initOK=" << i->reg->mb_initOK << endl;
}
if( !i->reg->mb_init )
if( !i->reg->mb_initOK )
continue;
i->value = sm->value;
updateRSProperty( &(*i),true);
updateRSProperty( &(*i),true );
return;
}
}
......@@ -1376,7 +1412,6 @@ bool MBTCPMaster::initRegInfo( RegInfo* r, UniXML_iterator& it, MBTCPMaster::RT
{
r->dev = dev;
r->mbval = it.getIntProp("default");
r->mb_init = it.getIntProp("tcp_mbinit");
if( dev->dtype == MBTCPMaster::dtRTU )
{
......@@ -1571,7 +1606,20 @@ bool MBTCPMaster::initItem( UniXML_iterator& it )
return false;
}
}
// Раз это регистр для записи, то как минимум надо сперва
// инициализировать значением из SM
ri->sm_initOK = it.getIntProp("tcp_sm_initOK");
ri->mb_initOK = true; // может быть переопределён если будет указан tcp_preinit="1" (см. ниже)
}
else
{
// Если это регистр для чтения, то сразу можно работать
// инициализировать не надо
ri->mb_initOK = true;
ri->sm_initOK = true;
}
RSProperty* p1 = addProp(ri->slst,p);
if( !p1 )
......@@ -1642,11 +1690,8 @@ bool MBTCPMaster::initItem( UniXML_iterator& it )
}
initRegList.push_back(ii);
}
else
{
ri->mb_init = true;
ri->sm_init = true;
ri->mb_initOK = false;
ri->sm_initOK = false;
}
return true;
......@@ -1947,8 +1992,6 @@ void MBTCPMaster::updateRTU( RegMap::iterator& rit )
for( PList::iterator it=r->slst.begin(); it!=r->slst.end(); ++it )
updateRSProperty( &(*it),false );
if( r->sm_init )
r->mb_init = true;
}
// -----------------------------------------------------------------------------
void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
......@@ -1961,6 +2004,11 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
if( !save && write_only )
return;
// если требуется инициализация и она ещё не произведена,
// то игнорируем
if( save && !r->mb_initOK )
return;
if( dlog.debugging(Debug::LEVEL3) )
dlog[Debug::LEVEL3] << "updateP: sid=" << p->si.id
<< " mbval=" << r->mbval
......@@ -1969,7 +2017,8 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
<< " nbit=" << p->nbit
<< " save=" << save
<< " ioype=" << p->stype
<< " mb_init=" << r->mb_init
<< " mb_initOK=" << r->mb_initOK
<< " sm_initOK=" << r->sm_initOK
<< endl;
try
......@@ -1979,11 +2028,15 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
ModbusRTU::DataBits16 b(r->mbval);
if( p->nbit >= 0 )
{
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
bool set = IOBase::processingAsDO( p, shm, force_out );
b.set(p->nbit,set);
r->mbval = b.mdata();
r->sm_initOK = true;
}
}
else
{
......@@ -1996,7 +2049,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
if( p->rnum <= 1 )
{
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
......@@ -2005,6 +2060,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
}
else
r->mbval = IOBase::processingAsAO( p, shm, force_out );
r->sm_initOK = true;
}
}
else
{
......@@ -2016,6 +2074,7 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
else
IOBase::processingAsAI( p, (signed short)(r->mbval), shm, force );
}
return;
}
......@@ -2025,7 +2084,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
}
else if( p->vType == VTypes::vtSigned )
{
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
......@@ -2034,6 +2095,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
}
else
r->mbval = (signed short)IOBase::processingAsAO( p, shm, force_out );
r->sm_initOK = true;
}
}
else
{
......@@ -2051,7 +2115,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
}
else if( p->vType == VTypes::vtUnsigned )
{
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
if( p->stype == UniversalIO::DigitalInput ||
p->stype == UniversalIO::DigitalOutput )
......@@ -2060,6 +2126,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
}
else
r->mbval = (unsigned short)IOBase::processingAsAO( p, shm, force_out );
r->sm_initOK = true;
}
}
else
{
......@@ -2084,12 +2153,16 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
return;
}
if( save && r->mb_init )
if( save && r->sm_initOK )
{
if( r->mb_initOK )
{
long v = IOBase::processingAsAO( p, shm, force_out );
VTypes::Byte b(r->mbval);
b.raw.b[p->nbyte-1] = v;
r->mbval = b.raw.w;
r->sm_initOK = true;
}
}
else
{
......@@ -2102,12 +2175,17 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
else if( p->vType == VTypes::vtF2 )
{
RegMap::iterator i(p->reg->rit);
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
float f = IOBase::processingFasAO( p, shm, force_out );
VTypes::F2 f2(f);
for( int k=0; k<VTypes::F2::wsize(); k++, i++ )
i->second->mbval = f2.raw.v[k];
r->sm_initOK = true;
}
}
else
{
......@@ -2124,13 +2202,16 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
else if( p->vType == VTypes::vtF4 )
{
RegMap::iterator i(p->reg->rit);
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
float f = IOBase::processingFasAO( p, shm, force_out );
VTypes::F4 f4(f);
for( int k=0; k<VTypes::F4::wsize(); k++, i++ )
i->second->mbval = f4.raw.v[k];
}
}
else
{
ModbusRTU::ModbusData* data = new ModbusRTU::ModbusData[VTypes::F4::wsize()];
......@@ -2146,12 +2227,17 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
else if( p->vType == VTypes::vtI2 )
{
RegMap::iterator i(p->reg->rit);
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
long v = IOBase::processingAsAO( p, shm, force_out );
VTypes::I2 i2(v);
for( int k=0; k<VTypes::I2::wsize(); k++, i++ )
i->second->mbval = i2.raw.v[k];
r->sm_initOK = true;
}
}
else
{
......@@ -2168,12 +2254,17 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
else if( p->vType == VTypes::vtU2 )
{
RegMap::iterator i(p->reg->rit);
if( save && r->mb_init )
if( save )
{
if( r->mb_initOK )
{
long v = IOBase::processingAsAO( p, shm, force_out );
VTypes::U2 u2(v);
for( int k=0; k<VTypes::U2::wsize(); k++, i++ )
i->second->mbval = u2.raw.v[k];
r->sm_initOK = true;
}
}
else
{
......@@ -2187,6 +2278,8 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
IOBase::processingAsAI( p, (unsigned int)u2, shm, force );
}
}
return;
}
catch(IOController_i::NameNotFound &ex)
{
......@@ -2213,6 +2306,10 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
{
dlog[Debug::LEVEL3] << myname << "(updateRSProperty): catch ..." << endl;
}
// Если SM стала (или была) недоступна
// то флаг инициализации надо сбросить
r->sm_initOK = false;
}
// -----------------------------------------------------------------------------
void MBTCPMaster::updateMTR( RegMap::iterator& rit )
......
......@@ -137,7 +137,7 @@
Помимо этого можно задавать следующие параметры:
- \b tcp_vtype - тип переменной. см VTypes::VType.
- \b tcp_rawdata - [1|0] - игнорировать или нет параметры калибровки
- \b tcp_rawdata - [0|1] - игнорировать или нет параметры калибровки
- \b tcp_iotype - [DI,DO,AI,AO] - переназначить тип датчика. По умолчанию используется поле iotype.
- \b tcp_nbit - номер бита в слове. Используется для DI,DO в случае когда для опроса используется
функция читающая слова (03
......@@ -145,6 +145,20 @@
- \b tcp_mboffset - "сдвиг"(может быть отрицательным) при опросе/записи.
Т.е. фактически будет опрошен/записан регистр "mbreg+mboffset".
Для инициализации "выходов" (регистров которые пишутся) можно использовать поля:
- \b tcp_preinit - [0|1] считать регистр перед использованием (при запуске процесса)
- \b tcp_init_mbfunc - Номер функции для инициализации. Если не указана, будет определена автоматически исходя из tcp_mbfunc.
- \b tcp_init_mbreg - Номер регистра откуда считывать значение для инициализации. Если это поле не указано используется tcp_mbreg.
Если указано tcp_preinit="1", то прежде чем начать писать регистр в устройство, будет произведено его чтение.
По умолчанию все "записываемые" регистры инициализируются значением из SM. Т.е. пока не будет первый раз считано значение из SM,
регистры в устройство писатся не будут. Чтобы отключить это поведение, можно указать параметр
- \b tcp_sm_initOK - [0|1] Игнорировать начальную инициализацию из SM (сразу писать в устройство)
При этом будет записывыться значение "default".
\warning Регистр должен быть уникальным. И может повторятся только если указан параметр \a nbit или \a nbyte.
*/
......@@ -222,7 +236,7 @@ class MBTCPMaster:
RegInfo():
mbval(0),mbreg(0),mbfunc(ModbusRTU::fnUnknown),
id(0),dev(0),mtrType(MTR::mtUnknown),
q_num(0),q_count(1),sm_init(false),mb_init(false)
q_num(0),q_count(1),mb_initOK(true),sm_initOK(true)
{}
ModbusRTU::ModbusData mbval;
......@@ -242,9 +256,16 @@ class MBTCPMaster:
RegMap::iterator rit;
// начальная инициалиазция
bool sm_init; /*!< инициализировалось ли значение в SM */
bool mb_init; /*!< инициализировалось ли в обмене */
// начальная инициалиазция для "записываемых" регистров
// Механизм:
// Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства.
// при этом флаг mb_init=false пока не пройдёт успешной инициализации
// Если tcp_preinit="0", то флаг mb_init сразу выставляется в true.
bool mb_initOK; /*!< инициализировалось ли значение из устройства */
// Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
// ещё не инициализировано из SM
bool sm_initOK; /*!< инициализировалось ли значение из SM */
};
friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
......
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