Commit 360848e3 authored by Pavel Vainerman's avatar Pavel Vainerman

(2.0): Переделал механизм уведомлений о "неопределённом состоянии" на…

(2.0): Переделал механизм уведомлений о "неопределённом состоянии" на использование сигналов. Дописал тест для проверки работы.
parent 586aad90
......@@ -19,6 +19,7 @@
<item name="changeTime" type="int" default="2000" min="0" comment="change state time" const="1" public="1" />
<item name="checkTime" type="int" default="3000" min="0" comment="check Working time" const="1" public="1" />
<item name="checkDependTime" type="int" default="5000" min="0" comment="check depend time" const="1" public="1" />
<item name="checkUndefTime" type="int" default="3000" min="0" comment="check undef time" const="1" public="1" />
</variables>
<smap>
<!-- name - название переменной в конф. файле -->
......@@ -31,6 +32,10 @@
<item name="d2_check_s" vartype="in" comment="состояние зависимого датчика"/>
<item name="set_d1_check_s" vartype="out" comment="для выставления датчика"/>
<item name="set_d2_check_s" vartype="out" comment="для выставления датчика"/>
<!-- проверка работы undefined state -->
<item name="undef_c" vartype="out" comment="аналоговый датчик (для проверки undef-состояния)"/>
<item name="check_undef_s" vartype="in" comment="датчик для выставления undef-состояния"/>
</smap>
<msgmap>
......
......@@ -30,7 +30,10 @@ void TestProc::sysCommand( UniSetTypes::SystemMessage* sm )
{
TestProc_SK::sysCommand(sm);
if( sm->command == SystemMessage::StartUp || sm->command == SystemMessage::WatchDog )
{
askTimer(tmCheckDepend,checkDependTime);
askTimer(tmCheckUndefState,checkUndefTime);
}
}
// -----------------------------------------------------------------------------
void TestProc::sensorInfo( SensorMessage *sm )
......@@ -53,6 +56,10 @@ void TestProc::sensorInfo( SensorMessage *sm )
dlog[Debug::LEVEL1] << myname << "(sensorInfo): STOP WORKING.." << endl;
}
}
else if( sm->id == check_undef_s )
{
dlog[Debug::LEVEL1] << myname << "(sensorInfo): CHECK UNDEFINED STATE ==> " << (sm->undefined==undef ? "OK" : "FAIL") << endl;
}
}
// -----------------------------------------------------------------------------
void TestProc::timerInfo( TimerMessage *tm )
......@@ -84,5 +91,15 @@ void TestProc::timerInfo( TimerMessage *tm )
dlog[Debug::LEVEL1] << myname << "(timerInfo): check depend ON: d1: " << ( getValue(d1_check_s) == test_val ? "OK" : "FAIL" ) << endl;
dlog[Debug::LEVEL1] << myname << "(timerInfo): check depend ON: d2: " << ( getValue(d2_check_s) == test_val ? "OK" : "FAIL" ) << endl;
}
else if( tm->id == tmCheckUndefState )
{
dlog[Debug::LEVEL1] << myname << "(timerInfo): Check undef state..." << endl;
undef ^= true;
si.id = undef_c;
si.node = conf->getLocalNode();
dlog[Debug::LEVEL1] << myname << "(timerInfo): set undefined=" << undef << endl;
ui.setUndefinedState( si, undef, getId() );
}
}
// -----------------------------------------------------------------------------
......@@ -18,7 +18,8 @@ class TestProc:
{
tmChange,
tmCheckWorking,
tmCheckDepend
tmCheckDepend,
tmCheckUndefState
};
virtual void step();
......@@ -28,6 +29,7 @@ class TestProc:
private:
bool state;
bool undef;
};
// -----------------------------------------------------------------------------
#endif // TestProc_H_
......
......@@ -41,6 +41,8 @@
set_d1_check_s="Input5_S"
d2_check_s="AI11_AS"
set_d2_check_s="AI11_AS"
undef_c="AI54_S"
check_undef_s="AI54_S"
/>
<IOControl name="IOControl"/>
......
......@@ -55,7 +55,11 @@ SharedMemory::SharedMemory( ObjectId id, string datafile, std::string confname )
// ----------------------
buildHistoryList(cnode);
signal_change_state().connect(sigc::mem_fun(*this, &SharedMemory::updateHistory));
signal_change_value().connect(sigc::mem_fun(*this, &SharedMemory::updateHistory));
for( History::iterator i=hist.begin(); i!=hist.end(); ++i )
histmap[i->fuse_id].push_back(i);
// ----------------------
restorer = NULL;
NCRestorer_XML* rxml = new NCRestorer_XML(datafile);
......@@ -734,27 +738,41 @@ void SharedMemory::saveHistory()
}
}
// -----------------------------------------------------------------------------
void SharedMemory::updateHistory( UniSetTypes::SensorMessage* sm )
void SharedMemory::updateHistory( IOStateList::iterator& s_it, IOController* )
{
if( hist.empty() )
return;
HistoryFuseMap::iterator i = histmap.find(s_it->second.si.id);
if( i == histmap.end() )
return;
long value = 0;
long sm_tv_sec = 0;
long sm_tv_usec = 0;
{
uniset_rwmutex_rlock lock(s_it->second.val_lock);
value = s_it->second.value;
sm_tv_sec = s_it->second.tv_sec;
sm_tv_usec = s_it->second.tv_usec;
}
if( dlog.debugging(Debug::INFO) )
{
dlog[Debug::INFO] << myname << "(updateHistory): "
<< " sid=" << sm->id
<< " value=" << sm->value
<< " sid=" << s_it->second.si.id
<< " value=" << value
<< endl;
}
for( History::iterator it=hist.begin(); it!=hist.end(); ++it )
for( HistoryItList::iterator it1=i->second.begin(); it1!=i->second.end(); ++it1 )
{
History::iterator it( (*it1) );
if( sm->sensor_type == UniversalIO::DI ||
sm->sensor_type == UniversalIO::DO )
if( s_it->second.type == UniversalIO::DI ||
s_it->second.type == UniversalIO::DO )
{
bool st = (bool)sm->value;
bool st = (bool)value;
if( it->fuse_invert )
st^=true;
......@@ -764,18 +782,18 @@ void SharedMemory::updateHistory( UniSetTypes::SensorMessage* sm )
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(updateHistory): HISTORY EVENT for " << (*it) << endl;
it->fuse_sec = sm->sm_tv_sec;
it->fuse_usec = sm->sm_tv_usec;
it->fuse_sec = sm_tv_sec;
it->fuse_usec = sm_tv_usec;
m_historySignal.emit( &(*it) );
}
}
else if( sm->sensor_type == UniversalIO::AI ||
sm->sensor_type == UniversalIO::AO )
else if( s_it->second.type == UniversalIO::AI ||
s_it->second.type == UniversalIO::AO )
{
if( sm->sensor_type == UniversalIO::DigitalInput ||
sm->sensor_type == UniversalIO::DigitalOutput )
{
bool st = (bool)sm->value;
bool st = (bool)value;
if( it->fuse_invert )
st^=true;
......@@ -784,15 +802,16 @@ void SharedMemory::updateHistory( UniSetTypes::SensorMessage* sm )
{
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(updateHistory): HISTORY EVENT for " << (*it) << endl;
it->fuse_tm = sm->tm;
it->fuse_sec = sm_tv_sec;
it->fuse_usec = sm_tv_usec;
m_historySignal.emit( &(*it) );
}
}
else if( sm->sensor_type == UniversalIO::AnalogInput ||
sm->sensor_type == UniversalIO::AnalogOutput )
{
if( !it->fuse_use_val )
if( value == it->fuse_val )
{
bool st = it->fuse_invert ? !sm->state : sm->state;
if( !st )
......@@ -800,20 +819,9 @@ void SharedMemory::updateHistory( UniSetTypes::SensorMessage* sm )
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(updateHistory): HISTORY EVENT for " << (*it) << endl;
it->fuse_tm = sm->tm;
m_historySignal.emit( &(*it) );
}
}
else
{
if( sm->value == it->fuse_val )
{
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(updateHistory): HISTORY EVENT for " << (*it) << endl;
it->fuse_tm = sm->tm;
m_historySignal.emit( &(*it) );
}
it->fuse_sec = sm_tv_sec;
it->fuse_usec = sm_tv_usec;
m_historySignal.emit( &(*it) );
}
}
}
......
......@@ -420,7 +420,7 @@ class SharedMemory:
History hist;
HistoryFuseMap histmap; /*!< map для оптимизации поиска */
virtual void updateHistory( UniSetTypes::SensorMessage* sm );
virtual void updateHistory( IOStateList::iterator& it, IOController* );
virtual void saveHistory();
void buildHistoryList( xmlNode* cnode );
......
......@@ -2,7 +2,7 @@
START=uniset-start.sh
${START} -f ./smemory-test --confile test.xml --dlog-add-levels level1 --localNode LocalhostNode \
${START} -f ./smemory-test --confile test.xml --dlog-add-levels level1 --localNode LocalhostNode $*
#--unideb-add-levels crit,warn,info
......
......@@ -98,15 +98,32 @@ class IOController:
public:
typedef sigc::signal<void,const IOController_i::SensorInfo&, long, IOController*> ChangeSignal;
// предварительное объявление, чтобы в структуре объявить итератор..
struct USensorIOInfo;
typedef std::map<UniSetTypes::KeyType, USensorIOInfo> IOStateList;
// ================== Достпуные сигналы =================
/*!
// \warning В сигнале напрямую передаётся итератор (т.е. по сути указатель на внутреннюю структуру!)
// Это не очень хорошо, с точки зрения "архитектуры", но оптимальнее по быстродействию!
// необходимо в обработчике не забывать использовать uniset_rwmutex_wrlock(val_lock) или uniset_rwmutex_rlock(val_lock)
*/
typedef sigc::signal<void, IOStateList::iterator&, IOController*> ChangeSignal;
typedef sigc::signal<void, IOStateList::iterator&, IOController*> ChangeUndefinedStateSignal;
// signal по изменению определённого датчика
ChangeSignal signal_change_value( UniSetTypes::ObjectId id, UniSetTypes::ObjectId node );
ChangeSignal signal_change_value( const IOController_i::SensorInfo& si );
// signal по изменению любого датчика
ChangeSignal signal_change_value();
// сигналы по изменению флага "неопределённое состояние" (обрыв датчика например)
ChangeUndefinedStateSignal signal_change_undefined_state( UniSetTypes::ObjectId id, UniSetTypes::ObjectId node );
ChangeUndefinedStateSignal signal_change_undefined_state( const IOController_i::SensorInfo& si );
ChangeUndefinedStateSignal signal_change_undefined_state();
// -----------------------------------------------------------------------------------------
// предварительное объявление, чтобы в структуре объявить итератор..
struct USensorIOInfo;
typedef std::map<UniSetTypes::KeyType, USensorIOInfo> IOStateList;
struct USensorIOInfo:
public IOController_i::SensorIOInfo
......@@ -138,14 +155,15 @@ class IOController:
// сигнал для реализации механизма зависимостией..
// (все зависимые датчики подключаются к нему (см. NCRestorer::init_depends_signals)
ChangeSignal changeSignal;
ChangeSignal sigChange;
ChangeUndefinedStateSignal sigUndefChange;
IOController_i::SensorInfo d_si; /*!< идентификатор датчика, от которого зависит данный */
long d_value; /*!< разрешающее работу значение датчика от которого зависит данный */
long d_off_value; /*!< блокирующее значение */
// функция обработки информации об изменении состояния датчика, от которого зависит данный
void checkDepend( const IOController_i::SensorInfo& si , long newval, IOController* );
void checkDepend( IOStateList::iterator& it, IOController* );
};
inline IOStateList::iterator ioBegin(){ return ioList.begin(); }
......@@ -252,6 +270,8 @@ class IOController:
private:
friend class NCRestorer;
ChangeSignal sigAnyChange;
ChangeSignal sigAnyUndefChange;
IOStateList ioList; /*!< список с текущим состоянием аналоговых входов/выходов */
UniSetTypes::uniset_rwmutex ioMutex; /*!< замок для блокирования совместного доступа к ioList */
......
......@@ -153,10 +153,6 @@ class IONotifyController:
virtual void localSetValue( IOController::IOStateList::iterator& it,
const IOController_i::SensorInfo& si,
CORBA::Long value, UniSetTypes::ObjectId sup_id );
// -----------------------------------------------
typedef sigc::signal<void,UniSetTypes::SensorMessage*> ChangeSignal;
ChangeSignal signal_change_state(){ return changeSignal; }
// -------------------- !!!!!!!!! ---------------------------------
virtual IONotifyController_i::ThresholdsListSeq* getThresholdsList();
......@@ -274,10 +270,10 @@ class IONotifyController:
NCRestorer* restorer;
// void onChangeUndefined( DependsList::iterator it, bool undefined );
void onChangeUndefinedState( IOStateList::iterator& it, IOController* ic );
UniSetTypes::uniset_rwmutex sig_mutex;
ChangeSignal changeSignal;
// UniSetTypes::uniset_rwmutex sig_mutex;
// ChangeSignal changeSignal;
private:
friend class NCRestorer;
......
......@@ -154,10 +154,35 @@ void IOController::localSetUndefinedState( IOStateList::iterator& li,
li->second.undefined = undefined;
} // unlock
// сперва локальные события...
try
{
if( changed )
li->second.changeSignal.emit(li->second.si, li->second.value, this);
li->second.sigUndefChange.emit(li, this);
}
catch(...){}
// потом глобольное, но конкретно для 'undefchange'
try
{
if( changed )
sigAnyUndefChange.emit(li, this);
}
catch(...){}
// теперь просто событие по изменению состояния
try
{
if( changed )
li->second.sigChange.emit(li, this);
}
catch(...){}
// глобальное по всем..
try
{
if( changed )
sigAnyChange.emit(li, this);
}
catch(...){}
}
......@@ -222,9 +247,6 @@ void IOController::localSetValue( IOController::IOStateList::iterator& li,
long prev = li->second.value;
if( !blocked )
li->second.real_value = li->second.value;
if( blocked )
{
li->second.real_value = value;
......@@ -252,7 +274,14 @@ void IOController::localSetValue( IOController::IOStateList::iterator& li,
try
{
if( changed )
li->second.changeSignal.emit(li->second.si, li->second.value, this);
li->second.sigChange.emit(li, this);
}
catch(...){}
try
{
if( changed )
sigAnyChange.emit(li, this);
}
catch(...){}
}
......@@ -728,16 +757,51 @@ IOController::ChangeSignal IOController::signal_change_value( UniSetTypes::Objec
}
uniset_rwmutex_rlock lock(it->second.val_lock);
return it->second.changeSignal;
return it->second.sigChange;
}
// -----------------------------------------------------------------------------
IOController::ChangeSignal IOController::signal_change_value()
{
return sigAnyChange;
}
// -----------------------------------------------------------------------------
IOController::ChangeUndefinedStateSignal IOController::signal_change_undefined_state( const IOController_i::SensorInfo& si )
{
return signal_change_undefined_state( si.id, si.node );
}
// -----------------------------------------------------------------------------
IOController::ChangeUndefinedStateSignal IOController::signal_change_undefined_state( UniSetTypes::ObjectId id, UniSetTypes::ObjectId node )
{
IOStateList::iterator it = ioList.find( key(id,node) );
if( it==ioList.end() )
{
ostringstream err;
err << myname << "(signal_change_undefine): вход(выход) с именем "
<< conf->oind->getNameById(id) << " не найден";
if( unideb.debugging(Debug::INFO) )
unideb[Debug::INFO] << err.str() << endl;
throw IOController_i::NameNotFound(err.str().c_str());
}
uniset_rwmutex_rlock lock(it->second.val_lock);
return it->second.sigUndefChange;
}
// -----------------------------------------------------------------------------
IOController::ChangeUndefinedStateSignal IOController::signal_change_undefined_state()
{
return sigAnyUndefChange;
}
// -----------------------------------------------------------------------------
void IOController::USensorIOInfo::checkDepend( const IOController_i::SensorInfo& dep_si , long newvalue, IOController* ic )
void IOController::USensorIOInfo::checkDepend( IOStateList::iterator& d_it, IOController* ic )
{
bool changed = false;
{
uniset_rwmutex_wrlock lock(val_lock);
bool prev = blocked;
blocked = ( newvalue == d_value ) ? false : true;
uniset_rwmutex_rlock dlock(d_it->second.val_lock);
blocked = ( d_it->second.value == d_value ) ? false : true;
changed = ( prev != blocked );
}
......
......@@ -65,6 +65,8 @@ IONotifyController::IONotifyController( ObjectId id, NCRestorer* d ):
trshMutex(string(conf->oind->getMapName(id))+"_trshMutex"),
maxAttemtps(conf->getPIntField("ConsumerMaxAttempts", 5))
{
signal_change_undefined_state().connect(sigc::mem_fun(*this, &IONotifyController::onChangeUndefinedState));
// добавляем фильтры
addIOFilter( sigc::mem_fun(this,&IONotifyController::myIOFilter) );
}
......@@ -366,13 +368,6 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
try
{
uniset_rwmutex_rlock l(sig_mutex);
changeSignal.emit(&sm);
}
catch(...){}
try
{
if( !li->second.db_ignore )
loggingInfo(sm);
}
......@@ -993,41 +988,43 @@ IONotifyController_i::ThresholdsListSeq* IONotifyController::getThresholdsList()
return res;
}
// -----------------------------------------------------------------------------
#if 0
void IONotifyController::onChangeUndefined( DependsList::iterator it, bool undefined )
void IONotifyController::onChangeUndefinedState( IOStateList::iterator& lit, IOController* ic )
{
SensorMessage sm;
USensorIOInfo& it(lit->second);
sm.id = it->si.id;
sm.node = it->si.node;
sm.undefined = undefined;
SensorMessage sm;
if( it->it != myioEnd() )
{
sm.value = it->it->second.value;
sm.sm_tv_sec = it->it->second.tv_sec;
sm.sm_tv_usec = it->it->second.tv_usec;
sm.priority = (Message::Priority)it->it->second.priority;
sm.sensor_type = it->it->second.type;
sm.ci = it->it->second.ci;
sm.supplier = DefaultObjectId;
}
// эти поля можно копировать без lock, т.к. они не меняются
sm.id = it.si.id;
sm.node = it.si.node;
sm.undefined = it.undefined;
sm.priority = (Message::Priority)it.priority;
sm.sensor_type = it.type;
sm.supplier = DefaultObjectId;
{ // lock
uniset_rwmutex_rlock lock(it.val_lock);
sm.value = it.value;
sm.sm_tv_sec = it.tv_sec;
sm.sm_tv_usec = it.tv_usec;
sm.ci = it.ci;
} // unlock
try
{
if( !it->it->second.db_ignore )
if( !it.db_ignore )
loggingInfo(sm);
}
catch(...){}
AskMap::iterator it1 = askIOList.find( key(it->si.id,it->si.node) );
AskMap::iterator it1 = askIOList.find( key(it.si.id,it.si.node) );
if( it1!=askIOList.end() )
{ // lock
uniset_rwmutex_rlock lock(askIOMutex);
send(it1->second, sm);
} // unlock
}
#endif
// -----------------------------------------------------------------------------
IDSeq* IONotifyController::askSensorsSeq( const UniSetTypes::IDSeq& lst,
const UniSetTypes::ConsumerInfo& ci,
......
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