Commit 2e01bbf4 authored by Pavel Vainerman's avatar Pavel Vainerman Committed by Pavel Vainerman

added support "freeze value"

parent a9921db2
......@@ -69,6 +69,9 @@ interface IOController_i : UniSetManager_i
void setUndefinedState(in uniset::ObjectId sid, in boolean undefined, in uniset::ObjectId sup_id )
raises(NameNotFound);
// "заморозка"/"разморозка" значения. set=true - выставить value и не менять, пока не будет вызван set=false
void freezeValue(in uniset::ObjectId sid, in boolean set, in long value, in uniset::ObjectId sup_id ) raises(NameNotFound);
UniversalIO::IOType getIOType(in uniset::ObjectId sid) raises(NameNotFound);
// --- Интерфейс для конфигурирования ---
......@@ -95,7 +98,8 @@ interface IOController_i : UniSetManager_i
long value; /*!< значение */
boolean undefined; /*!< признак неопределённости значения */
boolean blocked; /*!< данное значение блокировано другим */
long real_value; /*!< запомненное состояние, до блокировки */
boolean frozen; /*!< данное значение "заморожено" */
long real_value; /*!< запомненное состояние, до блокировки или заморозки */
UniversalIO::IOType type; /*!< тип */
long priority; /*!< приоритет уведомления */
IOController_i::SensorInfo si;
......
......@@ -56,6 +56,7 @@ static struct option longopts[] =
{ "quiet", no_argument, 0, 'q' },
{ "csv", required_argument, 0, 'z' },
{ "sendText", required_argument, 0, 'm' },
{ "freezeValue", required_argument, 0, 'n' },
{ NULL, 0, 0, 0 }
};
......@@ -79,6 +80,7 @@ int getCalibrate( const string& args, UInterface& ui );
int oinfo(const string& args, UInterface& ui, const string& userparam );
int apiRequest( const string& args, UInterface& ui, const string& query );
void sendText( const string& args, UInterface& ui, const string& txt, int mtype );
int freezeValue( const string& args, bool set, UInterface& ui );
// --------------------------------------------------------------------------
static void print_help(int width, const string& cmd, const string& help, const string& tab = " " )
{
......@@ -126,6 +128,7 @@ static void usage()
print_help(36, "-q|--quiet", "Выводит только результат.\n");
print_help(36, "-z|--csv", "Вывести результат (getValue) в виде val1,val2,val3...\n");
print_help(36, "-m|--sendText id1@node1,id2@node2,id3,.. mtype text", "Послать объектам текстовое сообщение text типа mtype\n");
print_help(36, "-n|--freezeValue id1@node1=val1,id2@node2=val2,id3=val3,.. set", "Выставить указанным датчикам соответствующие значения и заморозить их (set=true) или разморозить (set=false).\n");
cout << endl;
}
......@@ -199,6 +202,26 @@ int main(int argc, char** argv)
}
break;
case 'n': //--freezeValue
{
// смотрим второй параметр
if( checkArg(optind, argc, argv) == 0 )
{
if( !quiet )
cerr << "admin(freezeValue): Unknown 'set'. Use: id=v1,name=v2,name2@nodeX=v3 set" << endl;
return 1;
}
std::string sensors(optarg);
bool set = uni_atoi(argv[optind]);
auto conf = uniset_init(argc, argv, conffile);
UInterface ui(conf);
ui.initBackId(uniset::AdminID);
return freezeValue(sensors, set, ui);
}
break;
case 'g': //--getValue
case 'z': //--csv
{
......@@ -810,6 +833,68 @@ int getValue( const string& args, UInterface& ui )
return err;
}
// --------------------------------------------------------------------------------------
int freezeValue( const string& args, bool set, UInterface& ui )
{
int err = 0;
auto conf = ui.getConf();
auto sl = uniset::getSInfoList(args, conf);
if( verb )
cout << "====== freezeValue ======" << endl;
for( auto&& it : sl )
{
try
{
UniversalIO::IOType t = conf->getIOType(it.si.id);
if( verb )
{
cout << " value: " << it.val << endl;
cout << " name: (" << it.si.id << ") " << it.fname << endl;
cout << " iotype: " << t << endl;
cout << " text: " << conf->oind->getTextName(it.si.id) << "\n\n";
}
if( it.si.node == DefaultObjectId )
it.si.node = conf->getLocalNode();
switch(t)
{
case UniversalIO::DI:
case UniversalIO::DO:
case UniversalIO::AI:
case UniversalIO::AO:
ui.freezeValue(it.si, set, it.val, AdminID);
break;
default:
if( !quiet )
cerr << "FAILED: Unknown 'iotype' for " << it.fname << endl;
err = 1;
break;
}
}
catch( const uniset::Exception& ex )
{
if( !quiet )
cerr << "(setValue): " << ex << endl;;
err = 1;
}
catch( const std::exception& ex )
{
if( !quiet )
cerr << "std::exception: " << ex.what() << endl;
err = 1;
}
}
return err;
}
// --------------------------------------------------------------------------------------
int getCalibrate( const std::string& args, UInterface& ui )
{
int err = 0;
......
......@@ -19,6 +19,7 @@ ln -s -f admin.sh help
ln -s -f admin.sh oinfo
ln -s -f admin.sh apiRequest
ln -s -f admin.sh sendText
ln -s -f admin.sh freezeValue
ln -s -f ../../Utilities/scripts/uniset2-start.sh
ln -s -f ../../Utilities/scripts/uniset2-stop.sh stop.sh
......
......@@ -30,7 +30,7 @@
<item node="localhost" name="ReservSharedMemory"/>
</ReservList>
</SharedMemory>
<TestObject name="TestObject" sensor_s="DI2_S" output_c="AO2_C" dependDI_s="DependDI_S" dependAI_s="DependAI_S" monotonic_s="MonotonicAI_S" heartbeat_id="TO_Heartbeat_Counter" heartbeatTime="500" heartbeat_max="5"/>
<TestObject name="TestObject" sensor_s="DI2_S" output_c="AO2_C" dependDI_s="DependDI_S" dependAI_s="DependAI_S" monotonic_s="MonotonicAI_S" freeze_s="FreezeAI_S" heartbeat_id="TO_Heartbeat_Counter" heartbeatTime="500" heartbeat_max="5"/>
</settings>
<ObjectsMap idfromfile="1">
<nodes port="2809" unet_broadcast_ip="192.168.1.255" unet_broadcast_ip2="192.168.122.255">
......@@ -56,6 +56,8 @@
<item id="514" iotype="DI" name="Depend_BlockSensor_S" priority="Medium" textname="Block Sensor for depend"/>
<item id="515" iotype="DI" name="Threshold2_S" priority="Medium" textname="Threshold 2"/>
<item id="516" iotype="AI" name="MonotonicAI_S" priority="Medium" textname="monitonic AI"/>
<item id="517" iotype="AI" name="FreezeAI_S" priority="Medium" textname="Freeze AI sesnor"/>
</sensors>
<thresholds name="thresholds">
<sensor name="AI1_AS">
......
......@@ -323,3 +323,32 @@ TEST_CASE("[SM]: sendText", "[sm][sendText]")
REQUIRE( obj->getLastTextMessage() == txt );
REQUIRE( obj->getLastTextMessageType() == 3 );
}
// -----------------------------------------------------------------------------
TEST_CASE("[SM]: freezeValue", "[sm][freezeValue]")
{
InitTest();
IOController_i::SensorInfo si;
si.id = 517;
si.node = uniset_conf()->getLocalNode();
REQUIRE_NOTHROW( ui->setValue(517, 100) );
REQUIRE( ui->getValue(517) == 100 );
msleep(300);
REQUIRE( obj->in_freeze_s == 100 );
REQUIRE_NOTHROW( ui->freezeValue(si, true, 10) );
REQUIRE( ui->getValue(517) == 10 );
msleep(300);
REQUIRE( obj->in_freeze_s == 10 );
REQUIRE_NOTHROW( ui->setValue(517, 150) );
REQUIRE( ui->getValue(517) == 10 );
msleep(300);
REQUIRE( obj->in_freeze_s == 10 );
REQUIRE_NOTHROW( ui->freezeValue(si, false, 10) );
REQUIRE( ui->getValue(517) == 150 );
msleep(300);
REQUIRE( obj->in_freeze_s == 150 );
}
......@@ -13,6 +13,7 @@
<item name="dependDI_s" vartype="in" iotype="DI" comment="Test input"/>
<item name="dependAI_s" vartype="in" iotype="AI" comment="Test input"/>
<item name="monotonic_s" vartype="in" iotype="AI" comment="Test analog input"/>
<item name="freeze_s" vartype="in" iotype="AI" comment="Test freeze input"/>
</smap>
<msgmap>
......
......@@ -72,6 +72,10 @@ namespace uniset
CORBA::Boolean undefined,
uniset::ObjectId sup_id = uniset::DefaultObjectId ) override;
virtual void freezeValue( uniset::ObjectId sid,
CORBA::Boolean set,
CORBA::Long value,
uniset::ObjectId sup_id = uniset::DefaultObjectId ) override;
virtual IOController_i::SensorInfoSeq* getSensorSeq( const uniset::IDSeq& lst ) override;
virtual uniset::IDSeq* setOutputSeq( const IOController_i::OutSeq& lst, uniset::ObjectId sup_id ) override;
......@@ -178,6 +182,16 @@ namespace uniset
// -- работа через указатель ---
virtual long localSetValue( std::shared_ptr<USensorInfo>& usi, CORBA::Long value, uniset::ObjectId sup_id );
long localGetValue( std::shared_ptr<USensorInfo>& usi) ;
virtual void localFreezeValueIt( IOController::IOStateList::iterator& li,
uniset::ObjectId sid,
CORBA::Boolean set,
CORBA::Long value,
uniset::ObjectId sup_id );
virtual void localFreezeValue( std::shared_ptr<USensorInfo>& usi,
CORBA::Boolean set,
CORBA::Long value,
uniset::ObjectId sup_id );
#ifndef DISABLE_REST_API
// http API
......
......@@ -39,7 +39,6 @@
// -----------------------------------------------------------------------------------------
namespace uniset
{
/*!
* \class UInterface
* Универсальный интерфейс для взаимодействия между объектами (процессами).
......@@ -99,6 +98,8 @@ namespace uniset
// установка неопределённого состояния
void setUndefinedState( const IOController_i::SensorInfo& si, bool undefined, uniset::ObjectId supplier );
// заморозка значения (выставить указанный value и не менять)
void freezeValue( const IOController_i::SensorInfo& si, bool set, long value, uniset::ObjectId supplier = uniset::DefaultObjectId );
// ---------------------------------------------------------------
// Калибровка... пороги...
......
......@@ -277,6 +277,81 @@ namespace uniset
uwarn << set_err("UI(setUndefinedState): Timeout", si.id, si.node) << endl;
}
// ------------------------------------------------------------------------------------------------------------
void UInterface::freezeValue( const IOController_i::SensorInfo& si, bool set, long value, uniset::ObjectId sup_id )
{
if( si.id == uniset::DefaultObjectId )
{
uwarn << "UI(freezeValue): ID=uniset::DefaultObjectId" << endl;
return;
}
if( sup_id == uniset::DefaultObjectId )
sup_id = myid;
try
{
CORBA::Object_var oref;
try
{
oref = rcache.resolve(si.id, si.node);
}
catch( const uniset::NameNotFound& ) {}
for (size_t i = 0; i < uconf->getRepeatCount(); i++)
{
try
{
if( CORBA::is_nil(oref) )
oref = resolve( si.id, si.node );
IOController_i_var iom = IOController_i::_narrow(oref);
iom->freezeValue(si.id, set, value, sup_id );
return;
}
catch( const CORBA::TRANSIENT& ) {}
catch( const CORBA::OBJECT_NOT_EXIST& ) {}
catch( const CORBA::SystemException& ex ) {}
msleep(uconf->getRepeatTimeout());
oref = CORBA::Object::_nil();
}
}
catch( const uniset::TimeOut& ) {}
catch(const IOController_i::NameNotFound& ex)
{
rcache.erase(si.id, si.node);
uwarn << set_err("UI(freezeValue):" + string(ex.err), si.id, si.node) << endl;
}
catch(const IOController_i::IOBadParam& ex)
{
rcache.erase(si.id, si.node);
throw uniset::IOBadParam("UI(freezeValue): " + string(ex.err));
}
catch(const uniset::ORepFailed& )
{
rcache.erase(si.id, si.node);
// не смогли получить ссылку на объект
uwarn << set_err("UI(freezeValue): resolve failed", si.id, si.node) << endl;
}
catch(const CORBA::NO_IMPLEMENT& )
{
rcache.erase(si.id, si.node);
uwarn << set_err("UI(freezeValue): method no implement", si.id, si.node) << endl;
}
catch( const CORBA::OBJECT_NOT_EXIST& )
{
rcache.erase(si.id, si.node);
uwarn << set_err("UI(freezeValue): object not exist", si.id, si.node) << endl;
}
catch( const CORBA::COMM_FAILURE& ) {}
catch( const CORBA::SystemException& ex ) {}
catch(...) {}
rcache.erase(si.id, si.node);
uwarn << set_err("UI(freezeValue): Timeout", si.id, si.node) << endl;
}
// ------------------------------------------------------------------------------------------------------------
/*!
* \param id - идентификатор датчика
* \param value - значение, которое необходимо установить
......
......@@ -44,6 +44,7 @@ IOController::IOController(const string& name, const string& section):
isPingDBServer(true)
{
auto conf = uniset_conf();
if( conf )
dbserverID = conf->getDBServer();
}
......@@ -54,6 +55,7 @@ IOController::IOController(ObjectId id):
isPingDBServer(true)
{
auto conf = uniset_conf();
if( conf )
dbserverID = conf->getDBServer();
}
......@@ -104,7 +106,7 @@ IOController::InitSignal IOController::signal_init()
// ------------------------------------------------------------------------------------------
void IOController::activateInit()
{
for( auto && io : ioList )
for( auto&& io : ioList )
{
try
{
......@@ -207,6 +209,7 @@ void IOController::localSetUndefinedState( IOStateList::iterator& li,
uniset_rwmutex_wrlock lock(usi->val_lock);
changed = (usi->undefined != undefined);
usi->undefined = undefined;
if( usi->undef_value != not_specified_value )
{
if( undefined )
......@@ -262,6 +265,68 @@ void IOController::localSetUndefinedState( IOStateList::iterator& li,
catch(...) {}
}
// ------------------------------------------------------------------------------------------
void IOController::freezeValue( uniset::ObjectId sid,
CORBA::Boolean set,
CORBA::Long value,
uniset::ObjectId sup_id )
{
auto li = ioList.end();
localFreezeValueIt( li, sid, set, value, sup_id );
}
// ------------------------------------------------------------------------------------------
void IOController::localFreezeValueIt( IOController::IOStateList::iterator& li,
uniset::ObjectId sid,
CORBA::Boolean set,
CORBA::Long value,
uniset::ObjectId sup_id )
{
if( sup_id == uniset::DefaultObjectId )
sup_id = getId();
// сохранение текущего состояния
if( li == ioList.end() )
{
if( sid != DefaultObjectId )
li = ioList.find(sid);
}
if( li == ioList.end() )
{
ostringstream err;
err << myname << "(localFreezeValue): Unknown sensor (" << sid << ")"
<< "name: " << uniset_conf()->oind->getNameById(sid);
throw IOController_i::NameNotFound(err.str().c_str());
}
localFreezeValue(li->second, set, value, sup_id);
}
// ------------------------------------------------------------------------------------------
void IOController::localFreezeValue( std::shared_ptr<USensorInfo>& usi,
CORBA::Boolean set,
CORBA::Long value,
uniset::ObjectId sup_id )
{
ulog4 << myname << "(localFreezeValue): (" << usi->si.id << ")"
<< uniset_conf()->oind->getNameById(usi->si.id)
<< " value=" << value
<< " set=" << set
<< " supplier=" << sup_id
<< endl;
{
// выставляем флаг заморозки
uniset_rwmutex_wrlock lock(usi->val_lock);
usi->frozen = set;
usi->frozen_value = value;
// берём текущее значение, чтобы его не затереть
// при вызове setValue()
value = usi->real_value;
}
localSetValue(usi, value, sup_id);
}
// ------------------------------------------------------------------------------------------
void IOController::setValue( uniset::ObjectId sid, CORBA::Long value, uniset::ObjectId sup_id )
{
auto li = ioList.end();
......@@ -300,6 +365,7 @@ long IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
bool changed = false;
bool blockChanged = false;
bool freezeChanged = false;
long retValue = value;
{
......@@ -311,25 +377,30 @@ long IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
bool blocked = ( usi->blocked || usi->undefined );
changed = ( usi->real_value != value );
// Смотрим поменялось ли состояние блокировки.
// т.е. смотрим записано ли у нас уже value = d_off_value и флаг блокировки
// т.к. если blocked=true то должно быть usi->value = usi->d_off_value
// если флаг снимется, то значит должны "восстанавливать" значение из real_value
blockChanged = ( blocked != (usi->value == usi->d_off_value ) );
// Выставление запоненного значения (real_value)
// если снялась блокировка или заморозка
blockChanged = ( blocked != (usi->value == usi->d_off_value) );
freezeChanged = ( usi->frozen != (usi->value == usi->frozen_value) );
if( changed || blockChanged )
if( changed || blockChanged || freezeChanged )
{
ulog4 << myname << "(localSetValue): (" << usi->si.id << ")"
<< uniset_conf()->oind->getNameById(usi->si.id)
<< " newvalue=" << value
<< " value=" << usi->value
<< " blocked=" << usi->blocked
<< " frozen=" << usi->frozen
<< " real_value=" << usi->real_value
<< " supplier=" << sup_id
<< endl;
usi->real_value = value;
if( usi->frozen )
usi->value = usi->frozen_value;
else
usi->value = (blocked ? usi->d_off_value : value);
retValue = usi->value;
usi->nchanges++; // статистика
......@@ -350,7 +421,7 @@ long IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
try
{
if( changed || blockChanged )
if( changed || blockChanged || freezeChanged )
{
uniset_rwmutex_wrlock l(usi->changeMutex);
usi->sigChange.emit(usi, this);
......@@ -360,7 +431,7 @@ long IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
try
{
if( changed || blockChanged )
if( changed || blockChanged || freezeChanged )
{
std::lock_guard<std::mutex> l(siganyMutex);
sigAnyChange.emit(usi, this);
......@@ -462,7 +533,7 @@ void IOController::dumpToDB()
{
// lock
// uniset_mutex_lock lock(ioMutex, 100);
for( auto && usi : ioList )
for( auto&& usi : ioList )
{
auto& s = usi.second;
......@@ -615,6 +686,7 @@ IOController::USensorInfo::USensorInfo(): d_value(1), d_off_value(0)
dbignore = false;
undefined = false;
blocked = false;
frozen = false;
supplier = uniset::DefaultObjectId;
// стоит ли выставлять текущее время
......@@ -684,7 +756,7 @@ void IOController::for_iolist( IOController::UFunction f )
{
uniset_rwmutex_rlock lck(ioMutex);
for( auto && s : ioList )
for( auto&& s : ioList )
f(s.second);
}
// ----------------------------------------------------------------------------------------
......
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