Commit d42fb708 authored by Pavel Vainerman's avatar Pavel Vainerman

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

parent 7d041618
......@@ -270,6 +270,7 @@ void MBTCPMaster::poll()
it->second->resp_real = false;
}
updateSM();
allInitOK = false;
return;
}
......@@ -309,8 +310,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() )
......@@ -360,7 +365,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 )
......@@ -438,8 +445,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);
......@@ -448,6 +460,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);
......@@ -465,9 +485,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);
......@@ -476,22 +500,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) );
......@@ -521,9 +537,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 )
......@@ -608,8 +640,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;
......@@ -618,7 +655,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 )
......@@ -1066,14 +1102,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;
}
}
......@@ -1377,7 +1413,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 )
{
......@@ -1572,7 +1607,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 )
......@@ -1643,11 +1691,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;
......@@ -1949,8 +1994,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 )
......@@ -1963,6 +2006,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
......@@ -1971,7 +2019,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
......@@ -1981,11 +2030,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
{
......@@ -1998,7 +2051,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 )
......@@ -2007,6 +2062,9 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
}
else
r->mbval = IOBase::processingAsAO( p, shm, force_out );
r->sm_initOK = true;
}
}
else
{
......@@ -2018,6 +2076,7 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
else
IOBase::processingAsAI( p, (signed short)(r->mbval), shm, force );
}
return;
}
......@@ -2027,7 +2086,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 )
......@@ -2036,6 +2097,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
{
......@@ -2053,7 +2117,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 )
......@@ -2062,6 +2128,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
{
......@@ -2086,12 +2155,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
{
......@@ -2104,12 +2177,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
{
......@@ -2126,13 +2204,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()];
......@@ -2148,12 +2229,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
{
......@@ -2170,12 +2256,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
{
......@@ -2189,6 +2280,8 @@ void MBTCPMaster::updateRSProperty( RSProperty* p, bool write_only )
IOBase::processingAsAI( p, (unsigned int)u2, shm, force );
}
}
return;
}
catch(IOController_i::NameNotFound &ex)
{
......@@ -2215,6 +2308,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