Commit bef27bf8 authored by Pavel Vainerman's avatar Pavel Vainerman

(MB): начало работы над SafeMode - управление безопасным значением для датчиков.

parent e43016b1
......@@ -32,7 +32,7 @@ namespace uniset
os << "(" << inf.si.id << ")" << uniset_conf()->oind->getMapName(inf.si.id)
<< " card=" << inf.ncard << " channel=" << inf.channel << " subdev=" << inf.subdev
<< " aref=" << inf.aref << " range=" << inf.range
<< " default=" << inf.defval << " safety=" << inf.safety;
<< " default=" << inf.defval << " safeval=" << inf.safeval;
if( inf.cal.minRaw != inf.cal.maxRaw )
os << inf.cal;
......@@ -543,7 +543,7 @@ namespace uniset
ComediInterface* card = cards.getCard(it->ncard);
if( card == NULL || it->subdev == DefaultSubdev || it->channel == DefaultChannel )
if( card == NULL || it->subdev == IOBase::DefaultSubdev || it->channel == IOBase::DefaultChannel )
return;
if( it->si.id == DefaultObjectId )
......@@ -761,7 +761,7 @@ namespace uniset
inf.subdev = it.getIntProp("subdev");
if( inf.subdev < 0 )
inf.subdev = DefaultSubdev;
inf.subdev = IOBase::DefaultSubdev;
string jack = it.getProp("jack");
......@@ -778,7 +778,7 @@ namespace uniset
else if( jack == "J5" )
inf.subdev = 4;
else
inf.subdev = DefaultSubdev;
inf.subdev = IOBase::DefaultSubdev;
}
std::string prop_prefix( prefix + "_" );
......@@ -893,17 +893,17 @@ namespace uniset
try
{
if( it.subdev == DefaultSubdev || it.safety == NoSafety )
if( it.subdev == IOBase::DefaultSubdev || it.safeval == IOBase::UnusedSafeValue )
continue;
if( it.stype == UniversalIO::DO || it.lamp )
{
bool set = it.invert ? !((bool)it.safety) : (bool)it.safety;
bool set = it.invert ? !((bool)it.safeval) : (bool)it.safeval;
card->setDigitalChannel(it.subdev, it.channel, set);
}
else if( it.stype == UniversalIO::AO )
{
card->setAnalogChannel(it.subdev, it.channel, it.safety, it.range, it.aref);
card->setAnalogChannel(it.subdev, it.channel, it.safeval, it.range, it.aref);
}
}
catch( const std::exception& ex )
......@@ -928,7 +928,7 @@ namespace uniset
ComediInterface* card = cards.getCard(it.ncard);
if( card == NULL || it.subdev == DefaultSubdev || it.channel == DefaultChannel )
if( card == NULL || it.subdev == IOBase::DefaultSubdev || it.channel == IOBase::DefaultChannel )
continue;
try
......@@ -954,12 +954,12 @@ namespace uniset
for( auto& it : iomap )
{
if( it.subdev == DefaultSubdev )
if( it.subdev == IOBase::DefaultSubdev )
continue;
ComediInterface* card = cards.getCard(it.ncard);
if( card == NULL || it.subdev == DefaultSubdev || it.channel == DefaultChannel )
if( card == NULL || it.subdev == IOBase::DefaultSubdev || it.channel == IOBase::DefaultChannel )
continue;
try
......@@ -995,7 +995,7 @@ namespace uniset
for( auto& io : lst )
{
if( io->subdev == DefaultSubdev || io->channel == DefaultChannel )
if( io->subdev == IOBase::DefaultSubdev || io->channel == IOBase::DefaultChannel )
continue;
ComediInterface* card = cards.getCard(io->ncard);
......@@ -1080,17 +1080,17 @@ namespace uniset
try
{
if( it.subdev == DefaultSubdev || it.safety == NoSafety )
if( it.subdev == IOBase::DefaultSubdev || it.safeval == IOBase::UnusedSafeValue )
continue;
if( it.stype == UniversalIO::DO || it.lamp )
{
bool set = it.invert ? !((bool)it.safety) : (bool)it.safety;
bool set = it.invert ? !((bool)it.safeval) : (bool)it.safeval;
card->setDigitalChannel(it.subdev, it.channel, set);
}
else if( it.stype == UniversalIO::AO )
{
card->setAnalogChannel(it.subdev, it.channel, it.safety, it.range, it.aref);
card->setAnalogChannel(it.subdev, it.channel, it.safeval, it.range, it.aref);
}
}
catch( const uniset::Exception& ex )
......@@ -1393,7 +1393,7 @@ namespace uniset
ComediInterface* card = cards.getCard(it.ncard);
if( card == NULL || it.subdev == DefaultSubdev || it.channel == DefaultChannel )
if( card == NULL || it.subdev == IOBase::DefaultSubdev || it.channel == IOBase::DefaultChannel )
continue;
if( it.stype == UniversalIO::AO || it.stype == UniversalIO::DO )
......@@ -1475,7 +1475,7 @@ namespace uniset
// и сразу зажигаем, чтобы не было паузы
// (так комфортнее выглядит для оператора)
if( it.ignore || it.subdev == DefaultSubdev || it.channel == DefaultChannel )
if( it.ignore || it.subdev == IOBase::DefaultSubdev || it.channel == IOBase::DefaultChannel )
break;
ComediInterface* card = cards.getCard(it.ncard);
......@@ -1496,7 +1496,7 @@ namespace uniset
// и сразу зажигаем, чтобы не было паузы
// (так комфортнее выглядит для оператора)
if( it.ignore || it.subdev == DefaultSubdev || it.channel == DefaultChannel )
if( it.ignore || it.subdev == IOBase::DefaultSubdev || it.channel == IOBase::DefaultChannel )
break;
ComediInterface* card = cards.getCard(it.ncard);
......@@ -1517,7 +1517,7 @@ namespace uniset
// и сразу зажигаем, чтобы не было паузы
// (так комфортнее выглядит для оператора)
if( it.ignore || it.subdev == DefaultSubdev || it.channel == DefaultChannel )
if( it.ignore || it.subdev == IOBase::DefaultSubdev || it.channel == IOBase::DefaultChannel )
break;
ComediInterface* card = cards.getCard(it.ncard);
......
......@@ -221,6 +221,37 @@ namespace uniset
}
}
if( findArgParam("--" + prefix + "-safemode-reset-if-not-repond", conf->getArgc(), conf->getArgv()) != -1 )
{
safeMode = safeResetIfNotRespond;
vmonit(safeMode);
}
string safemode = conf->getArgParam("--" + prefix + "-safemode-external-control-sid", it.getProp("safeModeExternalControl"));
if( !safemode.empty() )
{
sidSafeModeExternal = conf->getSensorID(emode);
if( sidSafeModeExternal == DefaultObjectId )
{
ostringstream err;
err << myname << ": ID not found for " << safemode;
mbcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
// если указан датчик, то
safeMode = safeExternalControl;
vmonit(safeMode);
}
string safemodeValue = conf->getArgParam("--" + prefix + "-safemode-external-control-value", it.getProp("safeModeExternalControlValue"));
if( !safemodeValue.empty() )
valueSafeModeExternal = uni_atoi(safemodeValue);
vmonit(valueSafeModeExternal);
activateTimeout = conf->getArgPInt("--" + prefix + "-activate-timeout", 20000);
vmonit(allInitOK);
......@@ -281,6 +312,11 @@ namespace uniset
cout << "--prefix-default-mbinit-ok 0,1 - Флаг инициализации. 1 - не ждать первого обмена с устройством, а сохранить при старте в SM значение 'default'" << endl;
cout << "--prefix-query-max-count max - Максимальное количество запрашиваемых за один раз регистров (При условии no-query-optimization=0). По умолчанию: " << ModbusRTU::MAXDATALEN << "." << endl;
cout << endl;
cout << "SafeMode:";
cout << "--prefix-safemode-reset-if-not-respond - Включить режим сброса значений в safeval, при пропадании связи с устройством" << endl;
cout << "--prefix-safemode-external-control-sid id - Управление сбросом значений в безопасное состояние по внешнему датчику." << endl;
cout << "--prefix-safemode-external-control-value val - Значение срабатывания для датчика управления сбросом. Default: 1" << endl;
cout << endl;
cout << " Logs: " << endl;
cout << "--prefix-log-... - log control" << endl;
cout << " add-levels ... " << endl;
......@@ -294,6 +330,7 @@ namespace uniset
cout << "--prefix-logserver-port num - listen port. Default: ID" << endl;
cout << LogServer::help_print("prefix-logserver") << endl;
}
// -----------------------------------------------------------------------------
MBExchange::~MBExchange()
{
......@@ -2455,7 +2492,7 @@ namespace uniset
<< " tcp_mbreg=" << ModbusRTU::dat2str(ri->mbreg) << "(" << (int)ri->mbreg << ")"
<< " conflict with sensors " << sl.str() << endl;
abort(); // ABORT PROGRAM!!!!
std::abort(); // ABORT PROGRAM!!!!
return false;
}
......@@ -2468,7 +2505,7 @@ namespace uniset
mbcrit << myname << "(initItem): FAILED! Sharing SAVE (mbreg="
<< ModbusRTU::dat2str(ri->mbreg) << "(" << (int)ri->mbreg << ") already used)!"
<< " IGNORE --> " << it.getProp("name") << endl;
abort(); // ABORT PROGRAM!!!!
std::abort(); // ABORT PROGRAM!!!!
return false;
}
}
......@@ -2675,7 +2712,7 @@ namespace uniset
<< " nbit=" << p.nbit
<< " nbyte=" << p.nbyte
<< " rnum=" << p.rnum
<< " safety=" << p.safety
<< " safeval=" << p.safeval
<< " invert=" << p.invert;
if( p.stype == UniversalIO::AI || p.stype == UniversalIO::AO )
......@@ -2934,6 +2971,20 @@ namespace uniset
mbwarn << myname << "(askSensors): 'sidExchangeMode' catch..." << std::endl;
}
try
{
if( sidSafeModeExternal != DefaultObjectId )
shm->askSensor(sidSafeModeExternal, cmd);
}
catch( uniset::Exception& ex )
{
mbwarn << myname << "(askSensors): " << ex << std::endl;
}
catch(...)
{
mbwarn << myname << "(askSensors): 'sidSafeModeExternal' catch..." << std::endl;
}
for( auto it1 = devices.begin(); it1 != devices.end(); ++it1 )
{
auto d = it1->second;
......@@ -3287,6 +3338,20 @@ namespace uniset
return os;
}
// -----------------------------------------------------------------------------
ostream& operator<<( ostream& os, const MBExchange::SafeMode& sm )
{
if( sm == MBExchange::safeNone )
return os << "safeNone";
if( sm == MBExchange::safeResetIfNotRespond )
return os << "safeResetIfNotRespond";
if( sm == MBExchange::safeExternalControl )
return os << "safeExternalControl";
return os;
}
// -----------------------------------------------------------------------------
uniset::SimpleInfo* MBExchange::getInfo( const char* userparam )
{
uniset::SimpleInfo_var i = UniSetObject::getInfo(userparam);
......
......@@ -74,9 +74,18 @@ namespace uniset
emSkipSaveToSM = 3, /*!< не писать данные в SM (при этом работают и read и write функции) */
emSkipExchange = 4 /*!< отключить обмен */
};
friend std::ostream& operator<<( std::ostream& os, const ExchangeMode& em );
/*! Режимы работы процесса обмена */
enum SafeMode
{
safeNone = 0, /*!< не использовать безопасный режим (по умолчанию) */
safeResetIfNotRespond = 1, /*!< выставлять безопасное значение, если пропала связь с устройством */
safeExternalControl = 2 /*!< управление сбросом по внешнему датчику */
};
friend std::ostream& operator<<( std::ostream& os, const SafeMode& em );
enum DeviceType
{
dtUnknown, /*!< неизвестный */
......@@ -357,6 +366,11 @@ namespace uniset
IOController::IOStateList::iterator itExchangeMode;
long exchangeMode = {emNone}; /*!< режим работы см. ExchangeMode */
long safeMode = { safeNone }; /*!< режим безопасного состояния см. SafeMode */
uniset::ObjectId sidSafeModeExternal = { uniset::DefaultObjectId }; /*!< иденидентификатор для датчика безопасного режима */
IOController::IOStateList::iterator itSafeModeExternal;
long valueSafeModeExternal = { 1 };
std::atomic_bool activated = { false };
timeout_t activateTimeout = { 20000 }; // msec
bool noQueryOptimization = { false };
......
......@@ -1619,7 +1619,7 @@ namespace uniset
<< " stype=" << p.stype
<< " wnum=" << p.wnum
<< " nbyte=" << p.nbyte
<< " safety=" << p.safety
<< " safeval=" << p.safeval
<< " invert=" << p.invert
<< " regID=" << p.regID;
......
......@@ -30,13 +30,13 @@
namespace uniset
{
// -----------------------------------------------------------------------------
static const int DefaultSubdev = -1;
static const int DefaultChannel = -1;
static const int NoSafety = -1;
// -----------------------------------------------------------------------------
/*! Свойства переменной в/в */
struct IOBase
{
static const int DefaultSubdev = -1;
static const int DefaultChannel = -1;
static const int UnusedSafeValue = -1; // значение обозначающее, не использовать safe value
// т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
// приходится здесь тоже объявлять разрешенными только операции "перемещения"
IOBase( const IOBase& r ) = delete;
......@@ -53,7 +53,7 @@ namespace uniset
value(0),
craw(0),
cprev(0),
safety(0),
safeval(0),
defval(0),
df(1),
nofilter(false),
......@@ -108,7 +108,7 @@ namespace uniset
long value; /*!< текущее значение */
long craw; /*!< текущее 'сырое' значение до калибровки */
long cprev; /*!< предыдущее значение после калибровки */
long safety; /*!< безопасное состояние при завершении процесса */
long safeval; /*!< безопасное значение */
long defval; /*!< состояние по умолчанию (при запуске) */
DigitalFilter df; /*!< реализация программного фильтра */
......
......@@ -28,7 +28,7 @@ namespace uniset
{
return os << "(" << inf.si.id << ")" << uniset_conf()->oind->getMapName(inf.si.id)
<< " default=" << inf.defval
<< " safety=" << inf.safety
<< " safeval=" << inf.safeval
<< " stype=" << inf.stype
<< " calibration=" << inf.cal
<< " cdiagram=" << ( inf.cdiagram ? inf.cdiagram->getName() : "null" )
......@@ -632,7 +632,7 @@ namespace uniset
}
}
b->safety = initIntProp(it, "safety", prefix, init_prefix_only, NoSafety);
b->safeval = initIntProp(it, "safeval", prefix, init_prefix_only, UnusedSafeValue);
b->stype = uniset::getIOType(initProp(it, "iotype", prefix, init_prefix_only));
......@@ -814,7 +814,7 @@ namespace uniset
b.value = value;
b.craw = craw;
b.cprev = cprev;
b.safety = safety;
b.safeval = safeval;
b.defval = defval;
b.df = df;
b.nofilter = nofilter;
......@@ -853,7 +853,7 @@ namespace uniset
value = b.value;
craw = b.craw;
cprev = b.cprev;
safety = b.safety;
safeval = b.safeval;
defval = b.defval;
df = b.df;
nofilter = b.nofilter;
......
......@@ -30,7 +30,7 @@ TEST_CASE("[IOBase]: default constructor", "[iobase][extensions]")
CHECK( ib.value == 0 );
CHECK( ib.craw == 0 );
CHECK( ib.cprev == 0 ); /*!< предыдущее значение после калибровки */
CHECK( ib.safety == 0 ); /*!< безопасное состояние при завершении процесса */
CHECK( ib.safeval == 0 ); /*!< безопасное состояние при завершении процесса */
CHECK( ib.defval == 0 ); /*!< состояние по умолчанию (при запуске) */
CHECK( ib.nofilter == 0 ); /*!< отключение фильтра */
......
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