Commit 42a075e8 authored by Pavel Vainerman's avatar Pavel Vainerman

(MBExchange): SafeMode: step 2

parent bef27bf8
...@@ -893,7 +893,7 @@ namespace uniset ...@@ -893,7 +893,7 @@ namespace uniset
try try
{ {
if( it.subdev == IOBase::DefaultSubdev || it.safeval == IOBase::UnusedSafeValue ) if( it.subdev == IOBase::DefaultSubdev || !it.safevalDefined )
continue; continue;
if( it.stype == UniversalIO::DO || it.lamp ) if( it.stype == UniversalIO::DO || it.lamp )
...@@ -1080,7 +1080,7 @@ namespace uniset ...@@ -1080,7 +1080,7 @@ namespace uniset
try try
{ {
if( it.subdev == IOBase::DefaultSubdev || it.safeval == IOBase::UnusedSafeValue ) if( it.subdev == IOBase::DefaultSubdev || !it.safevalDefined )
continue; continue;
if( it.stype == UniversalIO::DO || it.lamp ) if( it.stype == UniversalIO::DO || it.lamp )
......
...@@ -63,8 +63,6 @@ namespace uniset ...@@ -63,8 +63,6 @@ namespace uniset
/*! глобальная функция для вывода help-а */ /*! глобальная функция для вывода help-а */
static void help_print( int argc, const char* const* argv ); static void help_print( int argc, const char* const* argv );
static const int NoSafetyState = -1;
/*! Режимы работы процесса обмена */ /*! Режимы работы процесса обмена */
enum ExchangeMode enum ExchangeMode
{ {
...@@ -84,7 +82,9 @@ namespace uniset ...@@ -84,7 +82,9 @@ namespace uniset
safeExternalControl = 2 /*!< управление сбросом по внешнему датчику */ safeExternalControl = 2 /*!< управление сбросом по внешнему датчику */
}; };
friend std::ostream& operator<<( std::ostream& os, const SafeMode& em );
friend std::string to_string( const SafeMode & m );
friend std::ostream& operator<<( std::ostream& os, const SafeMode& m );
enum DeviceType enum DeviceType
{ {
...@@ -139,33 +139,26 @@ namespace uniset ...@@ -139,33 +139,26 @@ namespace uniset
RegInfo& operator=(const RegInfo& r) = delete; RegInfo& operator=(const RegInfo& r) = delete;
RegInfo( RegInfo&& r ) = delete; RegInfo( RegInfo&& r ) = delete;
RegInfo& operator=(RegInfo&& r) = default; RegInfo& operator=(RegInfo&& r) = default;
RegInfo() = default;
RegInfo(): ModbusRTU::ModbusData mbval = { 0 };
mbval(0), mbreg(0), mbfunc(ModbusRTU::fnUnknown), ModbusRTU::ModbusData mbreg = { 0 }; /*!< регистр */
id(0), dev(0), ModbusRTU::SlaveFunctionCode mbfunc = { ModbusRTU::fnUnknown }; /*!< функция для чтения/записи */
rtuJack(RTUStorage::nUnknown), rtuChan(0),
mtrType(MTR::mtUnknown),
q_num(0), q_count(1), mb_initOK(false), sm_initOK(false)
{}
ModbusRTU::ModbusData mbval;
ModbusRTU::ModbusData mbreg; /*!< регистр */
ModbusRTU::SlaveFunctionCode mbfunc; /*!< функция для чтения/записи */
PList slst; PList slst;
ModbusRTU::RegID id; ModbusRTU::RegID id = { 0 };
std::shared_ptr<RTUDevice> dev; std::shared_ptr<RTUDevice> dev;
// only for RTU188 // only for RTU188
RTUStorage::RTUJack rtuJack; RTUStorage::RTUJack rtuJack = { RTUStorage::nUnknown };
int rtuChan; int rtuChan = { 0 };
// only for MTR // only for MTR
MTR::MTRType mtrType; /*!< тип регистра (согласно спецификации на MTR) */ MTR::MTRType mtrType = { MTR::mtUnknown }; /*!< тип регистра (согласно спецификации на MTR) */
// optimization // optimization
size_t q_num; /*!< number in query */ size_t q_num = { 0 }; /*!< number in query */
size_t q_count; /*!< count registers for query */ size_t q_count = { 0 }; /*!< count registers for query */
RegMap::iterator rit; RegMap::iterator rit;
...@@ -174,11 +167,11 @@ namespace uniset ...@@ -174,11 +167,11 @@ namespace uniset
// Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства. // Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства.
// при этом флаг mb_init=false пока не пройдёт успешной инициализации // при этом флаг mb_init=false пока не пройдёт успешной инициализации
// Если tcp_preinit="0", то флаг mb_init сразу выставляется в true. // Если tcp_preinit="0", то флаг mb_init сразу выставляется в true.
bool mb_initOK; /*!< инициализировалось ли значение из устройства */ bool mb_initOK = { false }; /*!< инициализировалось ли значение из устройства */
// Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров" // Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
// ещё не инициализировано из SM // ещё не инициализировано из SM
bool sm_initOK; /*!< инициализировалось ли значение из SM */ bool sm_initOK = { false }; /*!< инициализировалось ли значение из SM */
}; };
friend std::ostream& operator<<( std::ostream& os, RegInfo& r ); friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
...@@ -186,52 +179,42 @@ namespace uniset ...@@ -186,52 +179,42 @@ namespace uniset
struct RTUDevice struct RTUDevice
{ {
RTUDevice(): ModbusRTU::ModbusAddr mbaddr = { 0 }; /*!< адрес устройства */
mbaddr(0),
dtype(dtUnknown),
resp_id(uniset::DefaultObjectId),
resp_state(false),
resp_invert(false),
numreply(0),
prev_numreply(0),
ask_every_reg(false),
mode_id(uniset::DefaultObjectId),
mode(emNone),
speed(ComPort::ComSpeed38400),
rtu188(0)
{
}
ModbusRTU::ModbusAddr mbaddr; /*!< адрес устройства */
std::unordered_map<size_t, std::shared_ptr<RegMap>> pollmap; std::unordered_map<size_t, std::shared_ptr<RegMap>> pollmap;
DeviceType dtype; /*!< тип устройства */ DeviceType dtype = { dtUnknown }; /*!< тип устройства */
// resp - respond..(контроль наличия связи) // resp - respond..(контроль наличия связи)
uniset::ObjectId resp_id; uniset::ObjectId resp_id = { uniset::DefaultObjectId };
IOController::IOStateList::iterator resp_it; IOController::IOStateList::iterator resp_it;
DelayTimer resp_Delay; // таймер для формирования задержки на отпускание (пропадание связи) DelayTimer resp_Delay; // таймер для формирования задержки на отпускание (пропадание связи)
PassiveTimer resp_ptInit; // таймер для формирования задержки на инициализацию связи (задержка на выставление датчика связи после запуска) PassiveTimer resp_ptInit; // таймер для формирования задержки на инициализацию связи (задержка на выставление датчика связи после запуска)
bool resp_state; bool resp_state = { false };
bool resp_invert; bool resp_invert = { false };
bool resp_force = { false }; bool resp_force = { false };
Trigger trInitOK; // триггер для "инициализации" Trigger trInitOK; // триггер для "инициализации"
std::atomic<size_t> numreply; // количество успешных запросов.. std::atomic<size_t> numreply = { 0 }; // количество успешных запросов..
std::atomic<size_t> prev_numreply; std::atomic<size_t> prev_numreply = { 0 };
// //
bool ask_every_reg; /*!< опрашивать ли каждый регистр, независимо от результата опроса предыдущего. По умолчанию false - прервать опрос при первом же timeout */ bool ask_every_reg = { false }; /*!< опрашивать ли каждый регистр, независимо от результата опроса предыдущего. По умолчанию false - прервать опрос при первом же timeout */
// режим работы // режим работы
uniset::ObjectId mode_id; uniset::ObjectId mode_id = { uniset::DefaultObjectId };
IOController::IOStateList::iterator mode_it; IOController::IOStateList::iterator mode_it;
long mode; // режим работы с устройством (см. ExchangeMode) long mode = { emNone }; // режим работы с устройством (см. ExchangeMode)
// safe mode
long safeMode = { safeNone }; /*!< режим безопасного состояния см. SafeMode */
uniset::ObjectId safemode_id = { uniset::DefaultObjectId }; /*!< иденидентификатор для датчика безопасного режима */
IOController::IOStateList::iterator safemode_it;
long safemode_value = { 1 };
// return TRUE if state changed // return TRUE if state changed
bool checkRespond( std::shared_ptr<DebugStream>& log ); bool checkRespond( std::shared_ptr<DebugStream>& log );
// специфические поля для RS // специфические поля для RS
ComPort::Speed speed; ComPort::Speed speed = { ComPort::ComSpeed38400 };
std::shared_ptr<RTUStorage> rtu188; std::shared_ptr<RTUStorage> rtu188;
std::string getShortInfo() const; std::string getShortInfo() const;
...@@ -298,7 +281,6 @@ namespace uniset ...@@ -298,7 +281,6 @@ namespace uniset
RTUDeviceMap devices; RTUDeviceMap devices;
InitList initRegList; /*!< список регистров для инициализации */ InitList initRegList; /*!< список регистров для инициализации */
// uniset::uniset_rwmutex pollMutex;
virtual std::shared_ptr<ModbusClient> initMB( bool reopen = false ) = 0; virtual std::shared_ptr<ModbusClient> initMB( bool reopen = false ) = 0;
...@@ -312,10 +294,11 @@ namespace uniset ...@@ -312,10 +294,11 @@ namespace uniset
void updateRSProperty( RSProperty* p, bool write_only = false ); void updateRSProperty( RSProperty* p, bool write_only = false );
virtual void updateRespondSensors(); virtual void updateRespondSensors();
bool checkUpdateSM( bool wrFunc, long devMode ); bool isUpdateSM( bool wrFunc, long devMode ) const noexcept;
bool checkPoll( bool wrFunc ) const; bool isPollEnabled( bool wrFunc ) const noexcept;
bool isSafeMode( std::shared_ptr<RTUDevice>& dev ) const noexcept;
bool checkProcActive() const; bool isProcActive() const;
void setProcActive( bool st ); void setProcActive( bool st );
void waitSMReady(); void waitSMReady();
...@@ -353,7 +336,7 @@ namespace uniset ...@@ -353,7 +336,7 @@ namespace uniset
bool force_out = { false }; /*!< флаг означающий, принудительного чтения выходов */ bool force_out = { false }; /*!< флаг означающий, принудительного чтения выходов */
bool mbregFromID = { false }; bool mbregFromID = { false };
timeout_t polltime = { 100 }; /*!< переодичность обновления данных, [мсек] */ timeout_t polltime = { 100 }; /*!< переодичность обновления данных, [мсек] */
timeout_t sleepPause_msec; timeout_t sleepPause_msec = { 10 };
size_t maxQueryCount = { ModbusRTU::MAXDATALEN }; /*!< максимальное количество регистров для одного запроса */ size_t maxQueryCount = { ModbusRTU::MAXDATALEN }; /*!< максимальное количество регистров для одного запроса */
PassiveTimer ptHeartBeat; PassiveTimer ptHeartBeat;
...@@ -364,12 +347,7 @@ namespace uniset ...@@ -364,12 +347,7 @@ namespace uniset
uniset::ObjectId sidExchangeMode = { uniset::DefaultObjectId }; /*!< иденидентификатор для датчика режима работы */ uniset::ObjectId sidExchangeMode = { uniset::DefaultObjectId }; /*!< иденидентификатор для датчика режима работы */
IOController::IOStateList::iterator itExchangeMode; IOController::IOStateList::iterator itExchangeMode;
long exchangeMode = {emNone}; /*!< режим работы см. ExchangeMode */ 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 }; std::atomic_bool activated = { false };
timeout_t activateTimeout = { 20000 }; // msec timeout_t activateTimeout = { 20000 }; // msec
......
...@@ -150,13 +150,13 @@ void MBTCPMaster::final_thread() ...@@ -150,13 +150,13 @@ void MBTCPMaster::final_thread()
void MBTCPMaster::poll_thread() void MBTCPMaster::poll_thread()
{ {
// ждём начала работы..(см. MBExchange::activateObject) // ждём начала работы..(см. MBExchange::activateObject)
while( !checkProcActive() ) while( !isProcActive() )
{ {
uniset::uniset_rwmutex_rlock l(mutex_start); uniset::uniset_rwmutex_rlock l(mutex_start);
} }
// работаем // работаем
while( checkProcActive() ) while( isProcActive() )
{ {
try try
{ {
...@@ -178,7 +178,7 @@ void MBTCPMaster::poll_thread() ...@@ -178,7 +178,7 @@ void MBTCPMaster::poll_thread()
throw; throw;
} }
if( !checkProcActive() ) if( !isProcActive() )
break; break;
msleep(polltime); msleep(polltime);
......
...@@ -463,13 +463,13 @@ void MBTCPMultiMaster::sysCommand( const uniset::SystemMessage* sm ) ...@@ -463,13 +463,13 @@ void MBTCPMultiMaster::sysCommand( const uniset::SystemMessage* sm )
void MBTCPMultiMaster::poll_thread() void MBTCPMultiMaster::poll_thread()
{ {
// ждём начала работы..(см. MBExchange::activateObject) // ждём начала работы..(см. MBExchange::activateObject)
while( !checkProcActive() ) while( !isProcActive() )
{ {
uniset::uniset_rwmutex_rlock l(mutex_start); uniset::uniset_rwmutex_rlock l(mutex_start);
} }
// работаем.. // работаем..
while( checkProcActive() ) while( isProcActive() )
{ {
try try
{ {
...@@ -490,7 +490,7 @@ void MBTCPMultiMaster::poll_thread() ...@@ -490,7 +490,7 @@ void MBTCPMultiMaster::poll_thread()
mbwarn << myname << "(poll_thread): " << ex.what() << endl; mbwarn << myname << "(poll_thread): " << ex.what() << endl;
} }
if( !checkProcActive() ) if( !isProcActive() )
break; break;
msleep(polltime); msleep(polltime);
...@@ -499,7 +499,7 @@ void MBTCPMultiMaster::poll_thread() ...@@ -499,7 +499,7 @@ void MBTCPMultiMaster::poll_thread()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MBTCPMultiMaster::check_thread() void MBTCPMultiMaster::check_thread()
{ {
while( checkProcActive() ) while( isProcActive() )
{ {
for( auto && it : mblist ) for( auto && it : mblist )
{ {
...@@ -520,7 +520,7 @@ void MBTCPMultiMaster::check_thread() ...@@ -520,7 +520,7 @@ void MBTCPMultiMaster::check_thread()
<< " respond_force=" << it->respond_force << " respond_force=" << it->respond_force
<< " respond=" << it->respond << " respond=" << it->respond
<< " respond_invert=" << it->respond_invert << " respond_invert=" << it->respond_invert
<< " activated=" << checkProcActive() << " activated=" << isProcActive()
<< " ]" << " ]"
<< endl; << endl;
...@@ -528,7 +528,7 @@ void MBTCPMultiMaster::check_thread() ...@@ -528,7 +528,7 @@ void MBTCPMultiMaster::check_thread()
if( it->respond_init ) if( it->respond_init )
r = it->respondDelay.check( r ); r = it->respondDelay.check( r );
if( !checkProcActive() ) if( !isProcActive() )
break; break;
try try
...@@ -560,11 +560,11 @@ void MBTCPMultiMaster::check_thread() ...@@ -560,11 +560,11 @@ void MBTCPMultiMaster::check_thread()
mbcrit << myname << "(check): (respond) " << it->myname << " : " << ex.what() << std::endl; mbcrit << myname << "(check): (respond) " << it->myname << " : " << ex.what() << std::endl;
} }
if( !checkProcActive() ) if( !isProcActive() )
break; break;
} }
if( !checkProcActive() ) if( !isProcActive() )
break; break;
msleep(checktime); msleep(checktime);
......
...@@ -78,6 +78,8 @@ namespace uniset ...@@ -78,6 +78,8 @@ namespace uniset
- \b force [1,0] - "1" - обновлять значение датчика связи в SM принудительно на каждом цикле проверки ("0" - только по изменению). - \b force [1,0] - "1" - обновлять значение датчика связи в SM принудительно на каждом цикле проверки ("0" - только по изменению).
- \b exchangeModeID - идентификатор датчика режима работы (см. MBExchange::ExchangeMode). - \b exchangeModeID - идентификатор датчика режима работы (см. MBExchange::ExchangeMode).
- \b ask_every_reg - 1 - опрашивать ВСЕ регистры подряд, не обращая внимания на timeout. По умолчанию - "0" Т.е. опрос устройства (на текущем шаге цикла опроса), прерывается на первом же регистре, при опросе которого возникнет timeout. - \b ask_every_reg - 1 - опрашивать ВСЕ регистры подряд, не обращая внимания на timeout. По умолчанию - "0" Т.е. опрос устройства (на текущем шаге цикла опроса), прерывается на первом же регистре, при опросе которого возникнет timeout.
- \b safemodeSensor - датчик для управления "безопасным режимом". см. \ref MBTCPM_SafeMode
- \b safemodeSensorValue - значение датчика, при котором происходит сброс в "безопасные значения"
Секция <GateList> позволяет задать несколько каналов связи со Slave-устройством. Это удобно для случая, когда Slave имеет Секция <GateList> позволяет задать несколько каналов связи со Slave-устройством. Это удобно для случая, когда Slave имеет
более одного канала связи с ним (основной и резервный например). более одного канала связи с ним (основной и резервный например).
......
...@@ -201,7 +201,7 @@ bool RTUExchange::poll() ...@@ -201,7 +201,7 @@ bool RTUExchange::poll()
{ {
mb = initMB(false); mb = initMB(false);
if( !checkProcActive() ) if( !isProcActive() )
return false; return false;
updateSM(); updateSM();
...@@ -212,7 +212,7 @@ bool RTUExchange::poll() ...@@ -212,7 +212,7 @@ bool RTUExchange::poll()
if( !allInitOK ) if( !allInitOK )
firstInitRegisters(); firstInitRegisters();
if( !checkProcActive() ) if( !isProcActive() )
return false; return false;
ncycle++; ncycle++;
...@@ -301,7 +301,7 @@ bool RTUExchange::poll() ...@@ -301,7 +301,7 @@ bool RTUExchange::poll()
if( it == rmap->end() ) if( it == rmap->end() )
break; break;
if( !checkProcActive() ) if( !isProcActive() )
return false; return false;
} }
} }
...@@ -314,7 +314,7 @@ bool RTUExchange::poll() ...@@ -314,7 +314,7 @@ bool RTUExchange::poll()
// check thresholds // check thresholds
for( auto && t : thrlist ) for( auto && t : thrlist )
{ {
if( !checkProcActive() ) if( !isProcActive() )
return false; return false;
IOBase::processingThreshold(&t, shm, force); IOBase::processingThreshold(&t, shm, force);
......
...@@ -29,12 +29,12 @@ ...@@ -29,12 +29,12 @@
<SharedMemory name="SharedMemory" shmID="SharedMemory"/> <SharedMemory name="SharedMemory" shmID="SharedMemory"/>
<MBTCPMaster1 name="MBTCPMaster1" exchangeModeID="MBTCPMaster_Mode_AS"> <MBTCPMaster1 name="MBTCPMaster1" exchangeModeID="MBTCPMaster_Mode_AS">
<DeviceList> <DeviceList>
<item addr="0x01" invert="1" respondSensor="Slave_Not_Respond_S" timeout="1000"/> <item addr="0x01" invert="1" respondSensor="Slave_Not_Respond_S" timeout="1000" safemodeSensor="Slave1_SafemodeSensor_S" safemodeValue="42"/>
</DeviceList> </DeviceList>
</MBTCPMaster1> </MBTCPMaster1>
<MBTCPMultiMaster1 name="MBTCPMultiMaster1" poll_time="200" reply_timeout="60"> <MBTCPMultiMaster1 name="MBTCPMultiMaster1" poll_time="200" reply_timeout="60">
<DeviceList> <DeviceList>
<item addr="0x01" invert="1" respondSensor="Slave_Not_Respond_S" timeout="1000"/> <item addr="0x01" invert="1" respondSensor="Slave_Not_Respond_S" timeout="1000" safemodeSensor="Slave1_SafemodeSensor_S" safemodeValue="42" />
</DeviceList> </DeviceList>
<GateList> <GateList>
<item ip="127.0.0.1" port="20053" recv_timeout="200" invert="1" respondSensor="Slave1_Not_Respond_S"/> <item ip="127.0.0.1" port="20053" recv_timeout="200" invert="1" respondSensor="Slave1_Not_Respond_S"/>
...@@ -114,6 +114,11 @@ ...@@ -114,6 +114,11 @@
<item id="1027" mb="2" mbtype="rtu" mbaddr="0x01" mbreg="41" mbfunc="0x10" vtype="F2" iotype="AO" name="TestWrite1027_F2" precision="1" textname="F2: Тестовый регистр для 0x10"/> <item id="1027" mb="2" mbtype="rtu" mbaddr="0x01" mbreg="41" mbfunc="0x10" vtype="F2" iotype="AO" name="TestWrite1027_F2" precision="1" textname="F2: Тестовый регистр для 0x10"/>
<item id="1028" mb="2" mbtype="rtu" mbaddr="0x01" mbreg="47" mbfunc="0x03" vtype="F2" iotype="DI" name="TestWrite1028_F2" textname="F2: Тестовый регистр для 0x10"/> <item id="1028" mb="2" mbtype="rtu" mbaddr="0x01" mbreg="47" mbfunc="0x03" vtype="F2" iotype="DI" name="TestWrite1028_F2" textname="F2: Тестовый регистр для 0x10"/>
<!-- SafeMode tests -->
<item id="1040" name="Slave1_SafemodeSensor_S" iotype="AI" textname="Управление safeMode" />
<item id="1041" safeval="42" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="10" mbfunc="0x03" iotype="AI" name="SafeMode_TestRead03" textname="(safemode): Тестовый регистр для 0x03"/>
<item id="1042" safeval="1" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="11" mbfunc="0x02" iotype="DI" name="SafeMode_TestRead02" textname="(safemode): Тестовый регистр для 0x02"/>
<item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/> <item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/>
</sensors> </sensors>
......
...@@ -681,6 +681,34 @@ TEST_CASE("MBTCPMaster: 0x66 (file transfer)", "[modbus][0x66][mbmaster][mbtcpma ...@@ -681,6 +681,34 @@ TEST_CASE("MBTCPMaster: 0x66 (file transfer)", "[modbus][0x66][mbmaster][mbtcpma
WARN("Test of '0x66'..not yet.. "); WARN("Test of '0x66'..not yet.. ");
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: safe mode", "[modbus][safemode][mbmaster][mbtcpmaster]")
{
InitTest();
smi->setValue(1040,0); // отключаем safeMode
mbs->setReply(50);
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 50 );
// REQUIRE( ui->getValue(1042) == 1 );
mbs->setReply(0);
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 0 );
REQUIRE( ui->getValue(1042) == 0 );
smi->setValue(1040,42); // включаем safeMode
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 42 );
REQUIRE( ui->getValue(1042) == 1 );
smi->setValue(1040,0); // отключаем safeMode
mbs->setReply(0);
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 0 );
REQUIRE( ui->getValue(1042) == 0 );
}
// -----------------------------------------------------------------------------
#if 0 #if 0
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static bool init_iobase( IOBase* ib, const std::string& sensor ) static bool init_iobase( IOBase* ib, const std::string& sensor )
......
...@@ -151,3 +151,31 @@ TEST_CASE("MBTCPMultiMaster: rotate channel", "[modbus][mbmaster][mbtcpmultimast ...@@ -151,3 +151,31 @@ TEST_CASE("MBTCPMultiMaster: rotate channel", "[modbus][mbmaster][mbtcpmultimast
REQUIRE( ui->getValue(1003) == 100 ); REQUIRE( ui->getValue(1003) == 100 );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("MBTCPMultiMaster: safe mode", "[modbus][safemode][mbmaster][mbtcpmultimaster]")
{
InitTest();
ui->setValue(1040,0); // отключаем safeMode
mbs1->setReply(50);
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 50 );
// REQUIRE( ui->getValue(1042) == 1 );
mbs1->setReply(0);
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 0 );
REQUIRE( ui->getValue(1042) == 0 );
ui->setValue(1040,42); // включаем safeMode
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 42 );
REQUIRE( ui->getValue(1042) == 1 );
ui->setValue(1040,0); // отключаем safeMode
mbs1->setReply(0);
msleep(polltime + 200);
REQUIRE( ui->getValue(1041) == 0 );
REQUIRE( ui->getValue(1042) == 0 );
}
// -----------------------------------------------------------------------------
...@@ -35,7 +35,6 @@ namespace uniset ...@@ -35,7 +35,6 @@ namespace uniset
{ {
static const int DefaultSubdev = -1; static const int DefaultSubdev = -1;
static const int DefaultChannel = -1; static const int DefaultChannel = -1;
static const int UnusedSafeValue = -1; // значение обозначающее, не использовать safe value
// т.к. IOBase содержит rwmutex с запрещённым конструктором копирования // т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
// приходится здесь тоже объявлять разрешенными только операции "перемещения" // приходится здесь тоже объявлять разрешенными только операции "перемещения"
...@@ -108,8 +107,9 @@ namespace uniset ...@@ -108,8 +107,9 @@ namespace uniset
long value; /*!< текущее значение */ long value; /*!< текущее значение */
long craw; /*!< текущее 'сырое' значение до калибровки */ long craw; /*!< текущее 'сырое' значение до калибровки */
long cprev; /*!< предыдущее значение после калибровки */ long cprev; /*!< предыдущее значение после калибровки */
long safeval; /*!< безопасное значение */ long safeval; /*!< безопасное значение */
long defval; /*!< состояние по умолчанию (при запуске) */ long defval; /*!< состояние по умолчанию (при запуске) */
bool safevalDefined = { false }; /*!< флаг, означающий что safeval задан (можно использовать) */
DigitalFilter df; /*!< реализация программного фильтра */ DigitalFilter df; /*!< реализация программного фильтра */
bool nofilter; /*!< отключение фильтра */ bool nofilter; /*!< отключение фильтра */
......
...@@ -632,7 +632,11 @@ namespace uniset ...@@ -632,7 +632,11 @@ namespace uniset
} }
} }
b->safeval = initIntProp(it, "safeval", prefix, init_prefix_only, UnusedSafeValue); std::string ssafe = initProp(it, "safeval", prefix, init_prefix_only);
b->safevalDefined = !ssafe.empty();
if( b->safevalDefined )
b->safeval = uni_atoi(ssafe);
b->stype = uniset::getIOType(initProp(it, "iotype", prefix, init_prefix_only)); b->stype = uniset::getIOType(initProp(it, "iotype", prefix, init_prefix_only));
...@@ -815,6 +819,7 @@ namespace uniset ...@@ -815,6 +819,7 @@ namespace uniset
b.craw = craw; b.craw = craw;
b.cprev = cprev; b.cprev = cprev;
b.safeval = safeval; b.safeval = safeval;
b.safevalDefined = safevalDefined;
b.defval = defval; b.defval = defval;
b.df = df; b.df = df;
b.nofilter = nofilter; b.nofilter = nofilter;
...@@ -854,6 +859,7 @@ namespace uniset ...@@ -854,6 +859,7 @@ namespace uniset
craw = b.craw; craw = b.craw;
cprev = b.cprev; cprev = b.cprev;
safeval = b.safeval; safeval = b.safeval;
safevalDefined = b.safevalDefined;
defval = b.defval; defval = b.defval;
df = b.df; df = b.df;
nofilter = b.nofilter; nofilter = b.nofilter;
......
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