Commit 6c00d237 authored by Pavel Vainerman's avatar Pavel Vainerman

(SM): added undefined value for IOController

parent 4404d4a2
...@@ -50,6 +50,7 @@ interface IOController_i : UniSetManager_i ...@@ -50,6 +50,7 @@ interface IOController_i : UniSetManager_i
*/ */
exception Undefined exception Undefined
{ {
long value; // текущее значение (может быть специальным undefined_value)
}; };
/*! Информация о датчике */ /*! Информация о датчике */
......
...@@ -131,6 +131,9 @@ ...@@ -131,6 +131,9 @@
<item id="1064" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="208" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization5_F2" textname="F2: Тестовый регистр для 0x03"/> <item id="1064" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="208" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization5_F2" textname="F2: Тестовый регистр для 0x03"/>
<item id="1065" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="210" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization6_F2" textname="F2: Тестовый регистр для 0x03"/> <item id="1065" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="210" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization6_F2" textname="F2: Тестовый регистр для 0x03"/>
<!-- undefined state -->
<item id="1070" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="240" mbfunc="0x03" default="150" undefined_value="65535" breaklim="100" name="UndefinedState_FS" iotype="AI" textname="Тестирование неопределённого состояния"/>
<item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/> <item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/>
</sensors> </sensors>
......
...@@ -15,7 +15,7 @@ cd - ...@@ -15,7 +15,7 @@ cd -
--mbtcp-filter-value 1 \ --mbtcp-filter-value 1 \
--mbtcp-gateway-iaddr localhost \ --mbtcp-gateway-iaddr localhost \
--mbtcp-gateway-port 20048 \ --mbtcp-gateway-port 20048 \
--mbtcp-polltime 50 --mbtcp-recv-timeout 500 --mbtcp-polltime 50 --mbtcp-recv-timeout 500
#--mbtcp-log-add-levels any #--mbtcp-log-add-levels any
#--mbtcp-default-mbinit-ok 1 #--mbtcp-default-mbinit-ok 1
#--dlog-add-levels any #--dlog-add-levels any
......
...@@ -741,6 +741,31 @@ TEST_CASE("MBTCPMaster: safe mode (resetIfNotRespond)", "[modbus][safemode][mbma ...@@ -741,6 +741,31 @@ TEST_CASE("MBTCPMaster: safe mode (resetIfNotRespond)", "[modbus][safemode][mbma
REQUIRE( ui->getValue(1054) == 1 ); REQUIRE( ui->getValue(1054) == 1 );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: udefined value", "[modbus][undefined][mbmaster][mbtcpmaster]")
{
InitTest();
mbs->setReply(120);
msleep(polltime + 200);
REQUIRE( ui->getValue(1070) == 120 );
mbs->setReply(10);
msleep(polltime + 200);
try
{
ui->getValue(1070);
}
catch( IOController_i::Undefined& ex )
{
REQUIRE( ex.value == 65535 );
}
mbs->setReply(120);
msleep(polltime + 200);
REQUIRE( ui->getValue(1070) == 120 );
}
// -----------------------------------------------------------------------------
#if 0 #if 0
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static bool init_iobase( IOBase* ib, const std::string& sensor ) static bool init_iobase( IOBase* ib, const std::string& sensor )
......
...@@ -221,5 +221,35 @@ TEST_CASE("MBTCPMaster: safe mode (resetIfNotRespond)", "[modbus][safemode][mbma ...@@ -221,5 +221,35 @@ TEST_CASE("MBTCPMaster: safe mode (resetIfNotRespond)", "[modbus][safemode][mbma
msleep(5000); msleep(5000);
REQUIRE( ui->getValue(1053) == 53 ); REQUIRE( ui->getValue(1053) == 53 );
REQUIRE( ui->getValue(1054) == 1 ); REQUIRE( ui->getValue(1054) == 1 );
mbs1->setReply(0);
mbs2->setReply(0);
}
// -----------------------------------------------------------------------------
TEST_CASE("MBTCPMaster: udefined value", "[modbus][undefined][mbmaster][mbtcpmaster]")
{
InitTest();
mbs1->setReply(120);
mbs2->setReply(120);
msleep(polltime + 200);
REQUIRE( ui->getValue(1070) == 120 );
mbs1->setReply(10);
mbs2->setReply(10);
msleep(polltime + 200);
try
{
ui->getValue(1070);
}
catch( IOController_i::Undefined& ex )
{
REQUIRE( ex.value == 65535 );
}
mbs1->setReply(120);
mbs2->setReply(120);
msleep(polltime + 200);
REQUIRE( ui->getValue(1070) == 120 );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -769,7 +769,8 @@ namespace uniset ...@@ -769,7 +769,8 @@ namespace uniset
} }
catch( IOController_i::Undefined& ex ) catch( IOController_i::Undefined& ex )
{ {
hit.add( numeric_limits<long>::max(), it.size ); hit.add( ex.value, it.size );
// hit.add( numeric_limits<long>::max(), it.size );
} }
catch(...) {} catch(...) {}
} }
......
...@@ -161,10 +161,8 @@ namespace uniset ...@@ -161,10 +161,8 @@ namespace uniset
catch( IOController_i::Undefined& ex ) catch( IOController_i::Undefined& ex )
{ {
unetwarn << myname << "(updateFromSM): sid=" << i.id unetwarn << myname << "(updateFromSM): sid=" << i.id
<< " undefined state..." << endl; << " undefined state (value=" << ex.value << ")." << endl;
updateItem( i, ex.value );
if( i.undefined_value != not_specified_value )
updateItem( i, i.undefined_value );
} }
catch( std::exception& ex ) catch( std::exception& ex )
{ {
......
...@@ -56,7 +56,7 @@ void InitTest() ...@@ -56,7 +56,7 @@ void InitTest()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// pnum - минималный номер ожидаемого пакета ( 0 - любой пришедщий ) // pnum - минималный номер ожидаемого пакета ( 0 - любой пришедщий )
// ncycle - сколько пакетов разрешено "пропустить" прежде чем дождёмся нужного.. (чтобы не ждать бесконечно) // ncycle - сколько пакетов разрешено "пропустить" прежде чем дождёмся нужного.. (чтобы не ждать бесконечно)
static UniSetUDP::UDPMessage receive( unsigned int pnum = 0, timeout_t tout = 2000, int ncycle = 10 ) static UniSetUDP::UDPMessage receive( unsigned int pnum = 0, timeout_t tout = 2000, int ncycle = 20 )
{ {
UniSetUDP::UDPMessage pack; UniSetUDP::UDPMessage pack;
UniSetUDP::UDPPacket buf; UniSetUDP::UDPPacket buf;
...@@ -76,6 +76,9 @@ static UniSetUDP::UDPMessage receive( unsigned int pnum = 0, timeout_t tout = 20 ...@@ -76,6 +76,9 @@ static UniSetUDP::UDPMessage receive( unsigned int pnum = 0, timeout_t tout = 20
ncycle--; ncycle--;
} }
// if( pnum > 0 && pack.num < pnum )
// return UniSetUDP::UDPMessage(); // empty message
return pack; return pack;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -300,7 +303,7 @@ TEST_CASE("[UNetUDP]: check receiver", "[unetudp][receiver]") ...@@ -300,7 +303,7 @@ TEST_CASE("[UNetUDP]: check receiver", "[unetudp][receiver]")
REQUIRE( ui->getValue(11) == 0 ); REQUIRE( ui->getValue(11) == 0 );
send(pack); send(pack);
msleep(500); msleep(600);
REQUIRE( ui->getValue(8) == 100 ); REQUIRE( ui->getValue(8) == 100 );
REQUIRE( ui->getValue(9) == -100 ); REQUIRE( ui->getValue(9) == -100 );
REQUIRE( ui->getValue(10) == 1 ); REQUIRE( ui->getValue(10) == 1 );
...@@ -318,7 +321,7 @@ TEST_CASE("[UNetUDP]: check receiver", "[unetudp][receiver]") ...@@ -318,7 +321,7 @@ TEST_CASE("[UNetUDP]: check receiver", "[unetudp][receiver]")
pack.addDData(10, false); pack.addDData(10, false);
pack.addDData(11, true); pack.addDData(11, true);
send(pack); send(pack);
msleep(500); msleep(600);
REQUIRE( ui->getValue(8) == 10 ); REQUIRE( ui->getValue(8) == 10 );
REQUIRE( ui->getValue(9) == -10 ); REQUIRE( ui->getValue(9) == -10 );
REQUIRE( ui->getValue(10) == 0 ); REQUIRE( ui->getValue(10) == 0 );
...@@ -472,12 +475,13 @@ TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]") ...@@ -472,12 +475,13 @@ TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]")
{ {
InitTest(); InitTest();
UniSetUDP::UDPMessage pack = receive(); UniSetUDP::UDPMessage pack0 = receive();
ui->setValue(2, 110); ui->setValue(2, 110);
REQUIRE( ui->getValue(2) == 110 ); REQUIRE( ui->getValue(2) == 110 );
msleep(600); msleep(600);
pack = receive();
UniSetUDP::UDPMessage pack = receive( pack0.num + 1, 2000, 40 );
REQUIRE( pack.num != 0 ); REQUIRE( pack.num != 0 );
REQUIRE( pack.asize() == 4 ); REQUIRE( pack.asize() == 4 );
...@@ -489,7 +493,7 @@ TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]") ...@@ -489,7 +493,7 @@ TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]")
si.node = uniset_conf()->getLocalNode(); si.node = uniset_conf()->getLocalNode();
ui->setUndefinedState(si, true, 6000 /* TestProc */ ); ui->setUndefinedState(si, true, 6000 /* TestProc */ );
msleep(600); msleep(600);
pack = receive(); pack = receive(pack.num + 1);
REQUIRE( pack.num != 0 ); REQUIRE( pack.num != 0 );
REQUIRE( pack.asize() == 4 ); REQUIRE( pack.asize() == 4 );
...@@ -498,7 +502,7 @@ TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]") ...@@ -498,7 +502,7 @@ TEST_CASE("[UNetUDP]: check undefined value", "[unetudp][sender]")
ui->setUndefinedState(si, false, 6000 /* TestProc */ ); ui->setUndefinedState(si, false, 6000 /* TestProc */ );
msleep(600); msleep(600);
pack = receive(); pack = receive(pack.num + 1);
REQUIRE( pack.num != 0 ); REQUIRE( pack.num != 0 );
REQUIRE( pack.asize() == 4 ); REQUIRE( pack.asize() == 4 );
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include <unordered_map> #include <unordered_map>
#include <list> #include <list>
#include <limits>
#include <sigc++/sigc++.h> #include <sigc++/sigc++.h>
#include "IOController_i.hh" #include "IOController_i.hh"
#include "UniSetTypes.h" #include "UniSetTypes.h"
...@@ -59,15 +60,14 @@ namespace uniset ...@@ -59,15 +60,14 @@ namespace uniset
virtual uniset::SimpleInfo* getInfo( const char* userparam = "" ) override; virtual uniset::SimpleInfo* getInfo( const char* userparam = "" ) override;
// ----------------------------------------------------------------
// Публичный (IDL) интерфейс IOController_i
// ----------------------------------------------------------------
virtual CORBA::Long getValue( uniset::ObjectId sid ) override; virtual CORBA::Long getValue( uniset::ObjectId sid ) override;
// -------------------- !!!!!!!!! ---------------------------------
// Реализуются конкретным i/o контроллером
// Не забывайте писать реализацию этих функций
virtual void setValue( uniset::ObjectId sid, CORBA::Long value, virtual void setValue( uniset::ObjectId sid, CORBA::Long value,
uniset::ObjectId sup_id = uniset::DefaultObjectId ) override; uniset::ObjectId sup_id = uniset::DefaultObjectId ) override;
// ----------------------------------------------------------------
virtual void setUndefinedState( uniset::ObjectId sid, virtual void setUndefinedState( uniset::ObjectId sid,
CORBA::Boolean undefined, CORBA::Boolean undefined,
uniset::ObjectId sup_id = uniset::DefaultObjectId ) override; uniset::ObjectId sup_id = uniset::DefaultObjectId ) override;
...@@ -116,6 +116,8 @@ namespace uniset ...@@ -116,6 +116,8 @@ namespace uniset
struct USensorInfo; struct USensorInfo;
typedef std::unordered_map<uniset::ObjectId, std::shared_ptr<USensorInfo>> IOStateList; typedef std::unordered_map<uniset::ObjectId, std::shared_ptr<USensorInfo>> IOStateList;
static const long not_specified_value = { std::numeric_limits<long>::max() };
// ================== Достпуные сигналы ================= // ================== Достпуные сигналы =================
/*! /*!
// \warning В сигнале напрямую передаётся указатель на внутреннюю структуру! // \warning В сигнале напрямую передаётся указатель на внутреннюю структуру!
...@@ -330,6 +332,8 @@ namespace uniset ...@@ -330,6 +332,8 @@ namespace uniset
size_t nchanges = { 0 }; // количество изменений датчика size_t nchanges = { 0 }; // количество изменений датчика
long undef_value = { not_specified_value }; // значение для "неопределённого состояния датчика"
// функция обработки информации об изменении состояния датчика, от которого зависит данный // функция обработки информации об изменении состояния датчика, от которого зависит данный
void checkDepend( std::shared_ptr<USensorInfo>& d_usi, IOController* ); void checkDepend( std::shared_ptr<USensorInfo>& d_usi, IOController* );
......
...@@ -213,6 +213,9 @@ namespace uniset ...@@ -213,6 +213,9 @@ namespace uniset
inf->undefined = false; inf->undefined = false;
inf->real_value = inf->value; inf->real_value = inf->value;
if( !it.getProp("undefined_value").empty() )
inf->undef_value = it.getIntProp("undefined_value");
string d_txt( it.getProp("depend") ); string d_txt( it.getProp("depend") );
if( !d_txt.empty() ) if( !d_txt.empty() )
......
...@@ -163,7 +163,11 @@ long IOController::localGetValue( std::shared_ptr<USensorInfo>& usi ) ...@@ -163,7 +163,11 @@ long IOController::localGetValue( std::shared_ptr<USensorInfo>& usi )
uniset_rwmutex_rlock lock(usi->val_lock); uniset_rwmutex_rlock lock(usi->val_lock);
if( usi->undefined ) if( usi->undefined )
throw IOController_i::Undefined(); {
auto ex = IOController_i::Undefined();
ex.value = usi->value;
throw ex;
}
return usi->value; return usi->value;
} }
...@@ -198,10 +202,19 @@ void IOController::localSetUndefinedState( IOStateList::iterator& li, ...@@ -198,10 +202,19 @@ void IOController::localSetUndefinedState( IOStateList::iterator& li,
bool changed = false; bool changed = false;
{ {
auto usi = li->second;
// lock // lock
uniset_rwmutex_wrlock lock(li->second->val_lock); uniset_rwmutex_wrlock lock(usi->val_lock);
changed = (li->second->undefined != undefined); changed = (usi->undefined != undefined);
li->second->undefined = undefined; usi->undefined = undefined;
if( usi->undef_value != not_specified_value )
{
if( undefined )
usi->value = usi->undef_value;
else
usi->value = usi->real_value;
}
} // unlock } // unlock
// сперва локальные события... // сперва локальные события...
......
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