Commit cdd7d9ea authored by Pavel Vainerman's avatar Pavel Vainerman

(IOBase): ввёл механизм "зависимостей на уровне IOBase".

parent a265be6b
/*!
\page DependsPage Зависимости между датчиками
Существует два механизма реализующих зависимость между датчиками:
- \ref pgDep_secIOControl
- \ref pgDep_secIOBase
\section pgDep_secIOControl Зависимость на уровне IOController (SharedMemmory)
Механизм зависимостей реализован в классе IOController.
Пример записи "зависимости" в configure.xml:
......@@ -20,4 +26,19 @@
ПОКА РЕАЛИЗОВАНА ЗАВИСИМОСТЬ ТОЛЬКО ОТ ОДНОГО ДАТЧИКА!
т.е. <depend> может быть только один.
\section pgDep_secIOBase Зависимость на уровне IOBase
Механизм зависимостей между датчиками на уровне IOBase,
работает на уровне процессов обмена использующих IOBase.
В ним относятся IOControl, ModbusMaster (RTU,TCP) и т.п.
Плюсом данного механизма является, то, что он обеспечивает
для датчика (который зависит от другого) весь набор обработки,
поддерживаемый IOBase - это задержки на срабатывание, фильтры, калибровочные диаграммы и т.п. (см. \ref IOBase).
Чтобы задействовать данный механизм, достаточно у датчика указать следующие поля:
- \b depend="name"- имя датчика от которого зависит данный
- \b depend_value=".." - разрешающее значение (по умолчанию 1).
- \b depend_off_value="..." - значение которое будет иметь датчик, если он "заблокирован". По умолчанию - 0.
Следует иметь ввиду, что этот механизм не действует при сохранении значений, например при помощи uniset-admin,
в отличие от механизма \ref pgDep_secIOControl
*/
......@@ -36,6 +36,10 @@ static const int NoSafety = -1;
jar_state(false),
ondelay_state(false),
offdelay_state(false),
d_id(UniSetTypes::DefaultObjectId),
d_value(0),
d_off_value(0),
d_iotype(UniversalIO::UnknownIOType),
t_ai(UniSetTypes::DefaultObjectId)
{}
......@@ -46,6 +50,8 @@ static const int NoSafety = -1;
bool check_on_delay( bool val ); /*!< реализация задержки на включение */
bool check_off_delay( bool val ); /*!< реализация задержки на отключение */
bool check_depend( SMInterface* shm ); /*!< проверка разрешения(зависимости) от другого датчика */
IOController_i::SensorInfo si;
UniversalIO::IOTypes stype; /*!< тип канала (DI,DO,AI,AO) */
IOController_i::CalibrateInfo cal; /*!< калибровочные параметры */
......@@ -81,6 +87,13 @@ static const int NoSafety = -1;
bool ondelay_state; /*!< значение для задержки включения */
bool offdelay_state; /*!< значение для задержки отключения */
// Зависимость (d - depend)
UniSetTypes::ObjectId d_id; /*!< идентификатор датчика, от которого зависит данный */
IOController::AIOStateList::iterator d_ait; /*! итератор на датчик от которого зависит данный */
IOController::DIOStateList::iterator d_dit; /*! итератор на датчик от которого зависит данный */
long d_value; /*!< разрешающее работу значение датчика от которого зависит данный */
long d_off_value; /*!< блокирующее значение */
UniversalIO::IOTypes d_iotype;
// Порог
UniSetTypes::ObjectId t_ai; /*!< если данный датчик дискретный,
......
......@@ -92,6 +92,30 @@ bool IOBase::check_off_delay( bool val )
return offdelay_state;
}
// -----------------------------------------------------------------------------
bool IOBase::check_depend( SMInterface* shm )
{
if( d_id == DefaultObjectId )
return true;
if( d_iotype == UniversalIO::DigitalInput || d_iotype == UniversalIO::DigitalOutput )
{
if( shm->localGetState(d_dit,d_id) == (bool)d_value )
return true;
return false;
}
if( d_iotype == UniversalIO::AnalogInput || d_iotype == UniversalIO::AnalogOutput )
{
if( shm->localGetValue(d_ait,d_id) == d_value )
return true;
return false;
}
return true;
}
// -----------------------------------------------------------------------------
void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force )
{
// проверка на обрыв
......@@ -103,6 +127,11 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force
return;
}
// проверка зависимости
if( !it->check_depend(shm) )
val = it->d_off_value;
else
{
if( !it->nofilter && it->df.size() > 1 )
{
if( it->f_median )
......@@ -136,6 +165,7 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force
if( !it->noprecision && it->cal.precision > 0 )
val *= lround(pow10(it->cal.precision));
} // end of 'check_depend'
// если предыдущее значение "обрыв",
// то сбрасываем признак
......@@ -176,6 +206,11 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for
return;
}
// проверка зависимости
if( !it->check_depend(shm) )
val = it->d_off_value;
else
{
// Читаем с использованием фильтра...
if( !it->nofilter )
{
......@@ -188,6 +223,7 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for
IOController_i::CalibrateInfo* cal( &(it->cal) );
if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка
val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,true);
}
// если предыдущее значение "обрыв",
// то сбрасываем признак
......@@ -214,6 +250,11 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for
// -----------------------------------------------------------------------------
void IOBase::processingAsDI( IOBase* it, bool set, SMInterface* shm, bool force )
{
// проверка зависимости
if( !it->check_depend(shm) )
set = (bool)it->d_off_value;
else
{
// cout << "subdev: " << it->subdev << " chan: " << it->channel << " state=" << set << endl;
if( it->invert )
set ^= true;
......@@ -226,6 +267,7 @@ void IOBase::processingAsDI( IOBase* it, bool set, SMInterface* shm, bool force
// cout << "subdev: " << it->subdev << " chan: " << it->channel << " (on_delay)state=" << set << endl;
set = it->check_off_delay(set); // фильтр на отпускание
// cout << "subdev: " << it->subdev << " chan: " << it->channel << " (off_delay)state=" << set << endl;
}
{
uniset_spin_lock lock(it->val_lock);
......@@ -250,6 +292,10 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force )
uniset_spin_lock lock(it->val_lock);
long val = it->value;
// проверка зависимости
if( !it->check_depend(shm) )
return it->d_off_value;
if( force )
{
if( it->stype == UniversalIO::DigitalInput || it->stype == UniversalIO::DigitalOutput )
......@@ -296,6 +342,10 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force )
// -----------------------------------------------------------------------------
bool IOBase::processingAsDO( IOBase* it, SMInterface* shm, bool force )
{
// проверка зависимости
if( !it->check_depend(shm) )
return (bool)it->d_off_value;
uniset_spin_lock lock(it->val_lock);
bool set = it->value;
......@@ -313,8 +363,11 @@ bool IOBase::processingAsDO( IOBase* it, SMInterface* shm, bool force )
// -----------------------------------------------------------------------------
float IOBase::processingFasAO( IOBase* it, SMInterface* shm, bool force )
{
uniset_spin_lock lock(it->val_lock);
// проверка зависимости
if( !it->check_depend(shm) )
return (float)it->d_off_value;
uniset_spin_lock lock(it->val_lock);
long val = it->value;
if( force )
......@@ -453,7 +506,29 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
b->f_filter_iir = false;
shm->initAIterator(b->ait);
shm->initAIterator(b->d_ait);
shm->initDIterator(b->dit);
shm->initDIterator(b->d_dit);
string d_txt(it.getProp("depend"));
if( !it.getProp("depend").empty() )
{
b->d_id = conf->getSensorID(it.getProp("depend"));
if( b->d_id == DefaultObjectId )
{
if( dlog )
dlog[Debug::CRIT] << myname << "(IOBase::readItem): sensor='"
<< it.getProp("name") << "' err: "
<< " Unknown SensorID for depend='" << it.getProp("depend")
<< endl;
return false;
}
// по умолчанию срабатывание на "1"
b->d_value = it.getProp("depend_value").empty() ? 1 : it.getIntProp("depend_value");
b->d_off_value = it.getIntProp("depend_off_value");
b->d_iotype = conf->getIOType(b->d_id);
}
if( b->stype == UniversalIO::AnalogInput || b->stype == UniversalIO::AnalogOutput )
{
......
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