Commit 1e64d5c3 authored by Pavel Vainerman's avatar Pavel Vainerman

(UNetUDP): исправлена критическая ошибка в переключении каналов между собой,

добавлена возможность указать датчик, показывающий по какому каналу (1,2) идёт работа.
parent 246af23e
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
Name: libuniset2 Name: libuniset2
Version: 2.0 Version: 2.0
Release: alt22 Release: alt23
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
...@@ -409,12 +409,15 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname ...@@ -409,12 +409,15 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# .. # ..
%changelog %changelog
* Thu Mar 19 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt23
- unetudp: fxied critial bug in "switching channels" (thank`s Alexey Surov)
* Mon Mar 16 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt22 * Mon Mar 16 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt22
- codegen: add dumpIO(), str(), strval() functions (debug helpers) - codegen: add dumpIO(), str(), strval() functions (debug helpers)
* Thu Mar 12 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt21 * Thu Mar 12 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt21
- codegen: adjustment documentation - codegen: adjustment documentation
- unetudp: add tests, minor optimization (thank`s uzum) - unetudp: add tests, minor optimization (thank`s Alexey Vinogradov)
* Fri Mar 06 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt20 * Fri Mar 06 2015 Pavel Vainerman <pv@altlinux.ru> 2.0-alt20
- (modbustcpmaster): minor fixes in error messages - (modbustcpmaster): minor fixes in error messages
......
...@@ -331,14 +331,14 @@ MyClass_SK.cc: myclass.src.xml ...@@ -331,14 +331,14 @@ MyClass_SK.cc: myclass.src.xml
... ...
\endcode \endcode
- \b string \b str( ObjectId,showLinkName) - вывод названия указанного входа или выхода в формате "in_input1_s(Sensor1_S)". Если - \b string \b str(ObjectId,showLinkName) - вывод названия указанного входа или выхода в формате "in_input1_s(Sensor1_S)". Если
showLinkName=false, то будет сформирована строка "in_input1_s". Пример использования: showLinkName=false, то будет сформирована строка "in_input1_s". Пример использования:
\code \code
.. ..
myinfo << str(input1_s) << endl; myinfo << str(input1_s) << endl;
\endcode \endcode
- \b string \b strval( ObjectId,showLinkName) - вывод названия и текущего значения указанного входа или выхода в формате "in_input1_s(Sensor1_S)=1". Если - \b string \b strval(ObjectId,showLinkName) - вывод названия и текущего значения указанного входа или выхода в формате "in_input1_s(Sensor1_S)=1". Если
showLinkName=false, то будет сформирована строка "in_input1_s=1". Пример использования: showLinkName=false, то будет сформирована строка "in_input1_s=1". Пример использования:
\code \code
.. ..
......
...@@ -237,6 +237,20 @@ no_sender(false) ...@@ -237,6 +237,20 @@ no_sender(false)
} }
} }
string s_numchannel_id(n_it.getProp("unet_numchannel_id"));
UniSetTypes::ObjectId numchannel_id = UniSetTypes::DefaultObjectId;
if( !s_numchannel_id.empty() )
{
numchannel_id = conf->getSensorID(s_numchannel_id);
if( numchannel_id == UniSetTypes::DefaultObjectId )
{
ostringstream err;
err << myname << ": Unknown NumChannelID.. Not found id for '" << s_numchannel_id << "'" << endl;
dcrit << myname << "(init): " << err.str() << endl;
throw SystemError(err.str());
}
}
dinfo << myname << "(init): (node='" << n << "') add receiver " dinfo << myname << "(init): (node='" << n << "') add receiver "
<< h2 << ":" << p2 << endl; << h2 << ":" << p2 << endl;
auto r = make_shared<UNetReceiver>(h,p,shm); auto r = make_shared<UNetReceiver>(h,p,shm);
...@@ -291,6 +305,7 @@ no_sender(false) ...@@ -291,6 +305,7 @@ no_sender(false)
ReceiverInfo ri(r,r2); ReceiverInfo ri(r,r2);
ri.setRespondID(resp_comm_id,resp_invert); ri.setRespondID(resp_comm_id,resp_invert);
ri.setLostPacketsID(lp_comm_id); ri.setLostPacketsID(lp_comm_id);
ri.setChannelNumID(numchannel_id);
recvlist.push_back(ri); recvlist.push_back(ri);
} }
...@@ -446,6 +461,24 @@ void UNetExchange::ReceiverInfo::step( const std::shared_ptr<SMInterface> shm, c ...@@ -446,6 +461,24 @@ void UNetExchange::ReceiverInfo::step( const std::shared_ptr<SMInterface> shm, c
{ {
dcrit << myname << "(ReceiverInfo::step): (lostpackets): " << ex << std::endl; dcrit << myname << "(ReceiverInfo::step): (lostpackets): " << ex << std::endl;
} }
try
{
if( sidChannelNum != DefaultObjectId )
{
long c = 0;
if( r1 && !r1->isLockUpdate() )
c = 1;
if( r2 && !r2->isLockUpdate() )
c = 2;
shm->localSetValue(itChannelNum,sidChannelNum,c,shm->ID());
}
}
catch( const Exception& ex )
{
dcrit << myname << "(ReceiverInfo::step): (channelnum): " << ex << std::endl;
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetExchange::sysCommand( const UniSetTypes::SystemMessage *sm ) void UNetExchange::sysCommand( const UniSetTypes::SystemMessage *sm )
...@@ -669,38 +702,78 @@ std::shared_ptr<UNetExchange> UNetExchange::init_unetexchange( int argc, const c ...@@ -669,38 +702,78 @@ std::shared_ptr<UNetExchange> UNetExchange::init_unetexchange( int argc, const c
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceiver::Event ev ) void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceiver::Event ev )
{ {
// пока, что другие события нас не интересуют
if( ev != UNetReceiver::evTimeout )
return;
for( auto &it: recvlist ) for( auto &it: recvlist )
{ {
if( it.r1 == r ) if( it.r1 == r )
{ {
// если нет второго канала if( ev == UNetReceiver::evTimeout )
// то и переключать некуда {
if( !it.r2 ) // если нет второго канала или нет связи
return; // то и переключать не надо
if( !it.r2 || !it.r2->isRecvOK() )
// пропала связь по первому каналу... return;
// переключаемся на второй
it.r1->setLockUpdate(true); // пропала связь по первому каналу...
it.r2->setLockUpdate(false); // переключаемся на второй
it.r1->setLockUpdate(true);
dinfo << myname << "(event): " << r->getName() it.r2->setLockUpdate(false);
<< ": timeout for channel1.. select channel 2" << endl;
dlog8 << myname << "(event): " << r->getName()
<< ": timeout for channel1.. select channel 2" << endl;
}
else if( ev == UNetReceiver::evOK )
{
// если связь восстановилась..
// проверяем, а что там со вторым каналом
// если у него связи нет, то забираем себе..
if( !it.r2 || !it.r2->isRecvOK() )
{
it.r1->setLockUpdate(false);
if( it.r2 )
it.r2->setLockUpdate(true);
dlog8 << myname << "(event): " << r->getName()
<< ": link failed for channel2.. select again channel1.." << endl;
}
}
return; return;
} }
if( it.r2 == r ) if( it.r2 == r )
{ {
// пропала связь по второму каналу... if( ev == UNetReceiver::evTimeout )
// переключаемся на первый {
it.r1->setLockUpdate(false); // если первого канала нет или нет связи
it.r2->setLockUpdate(true); // то и переключать не надо
if( !it.r1 || !it.r1->isRecvOK() )
return;
dinfo << myname << "(event): " << r->getName() // пропала связь по второму каналу...
// переключаемся на первый
it.r1->setLockUpdate(false);
it.r2->setLockUpdate(true);
dlog8 << myname << "(event): " << r->getName()
<< ": timeout for channel2.. select channel 1" << endl; << ": timeout for channel2.. select channel 1" << endl;
}
else if( ev == UNetReceiver::evOK )
{
// если связь восстановилась..
// проверяем, а что там со первым каналом
// если у него связи нет, то забираем себе..
if( !it.r1 || !it.r1->isRecvOK() )
{
if( it.r1 )
it.r1->setLockUpdate(true);
it.r2->setLockUpdate(false);
dlog8 << myname << "(event): " << r->getName()
<< ": link failed for channel1.. select again channel2.." << endl;
}
}
return; return;
} }
} }
......
...@@ -142,14 +142,16 @@ class UNetExchange: ...@@ -142,14 +142,16 @@ class UNetExchange:
ReceiverInfo():r1(nullptr),r2(nullptr), ReceiverInfo():r1(nullptr),r2(nullptr),
sidRespond(UniSetTypes::DefaultObjectId), sidRespond(UniSetTypes::DefaultObjectId),
respondInvert(false), respondInvert(false),
sidLostPackets(UniSetTypes::DefaultObjectId) sidLostPackets(UniSetTypes::DefaultObjectId),
sidChannelNum(UniSetTypes::DefaultObjectId)
{} {}
ReceiverInfo( const std::shared_ptr<UNetReceiver>& _r1, const std::shared_ptr<UNetReceiver>& _r2 ): ReceiverInfo( const std::shared_ptr<UNetReceiver>& _r1, const std::shared_ptr<UNetReceiver>& _r2 ):
r1(_r1),r2(_r2), r1(_r1),r2(_r2),
sidRespond(UniSetTypes::DefaultObjectId), sidRespond(UniSetTypes::DefaultObjectId),
respondInvert(false), respondInvert(false),
sidLostPackets(UniSetTypes::DefaultObjectId) sidLostPackets(UniSetTypes::DefaultObjectId),
sidChannelNum(UniSetTypes::DefaultObjectId)
{} {}
std::shared_ptr<UNetReceiver> r1; /*!< приём по первому каналу */ std::shared_ptr<UNetReceiver> r1; /*!< приём по первому каналу */
...@@ -163,21 +165,26 @@ class UNetExchange: ...@@ -163,21 +165,26 @@ class UNetExchange:
respondInvert = invert; respondInvert = invert;
} }
inline void setLostPacketsID( UniSetTypes::ObjectId id ){ sidLostPackets = id; } inline void setLostPacketsID( UniSetTypes::ObjectId id ){ sidLostPackets = id; }
inline void setChannelNumID( UniSetTypes::ObjectId id ){ sidChannelNum = id; }
inline void initIterators( const std::shared_ptr<SMInterface> shm ) inline void initIterators( const std::shared_ptr<SMInterface> shm )
{ {
shm->initIterator(itLostPackets); shm->initIterator(itLostPackets);
shm->initIterator(itRespond); shm->initIterator(itRespond);
shm->initIterator(itChannelNum);
} }
// Сводная информация по двум каналам // Сводная информация по двум каналам
// сумма потерянных пакетов и наличие связи // сумма потерянных пакетов и наличие связи
// хотя бы по одному каналу // хотя бы по одному каналу, номер рабочего канала
// ( реализацию см. ReceiverInfo::step() ) // ( реализацию см. ReceiverInfo::step() )
UniSetTypes::ObjectId sidRespond; UniSetTypes::ObjectId sidRespond;
IOController::IOStateList::iterator itRespond; IOController::IOStateList::iterator itRespond;
bool respondInvert; bool respondInvert;
UniSetTypes::ObjectId sidLostPackets; UniSetTypes::ObjectId sidLostPackets;
IOController::IOStateList::iterator itLostPackets; IOController::IOStateList::iterator itLostPackets;
UniSetTypes::ObjectId sidChannelNum;
IOController::IOStateList::iterator itChannelNum;
}; };
typedef std::deque<ReceiverInfo> ReceiverList; typedef std::deque<ReceiverInfo> ReceiverList;
......
...@@ -67,6 +67,7 @@ class UNetReceiver: ...@@ -67,6 +67,7 @@ class UNetReceiver:
// блокировать сохранение данных в SM // блокировать сохранение данных в SM
void setLockUpdate( bool st ); void setLockUpdate( bool st );
inline bool isLockUpdate(){ return lockUpdate; }
void resetTimeout(); void resetTimeout();
......
...@@ -26,6 +26,8 @@ static int s_numpack = 1; ...@@ -26,6 +26,8 @@ static int s_numpack = 1;
static ObjectId node2_respond_s = 12; static ObjectId node2_respond_s = 12;
static ObjectId node2_lostpackets_as = 13; static ObjectId node2_lostpackets_as = 13;
static int maxDifferense = 5; // см. unetudp-test-configure.xml --unet-maxdifferense static int maxDifferense = 5; // см. unetudp-test-configure.xml --unet-maxdifferense
static int recvTimeout = 1000; // --unet-recv-timeout
static ObjectId node1_numchannel_as = 14;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void InitTest() void InitTest()
{ {
...@@ -417,3 +419,21 @@ TEST_CASE("[UNetUDP]: bad packet number","[unetudp][badnumber]") ...@@ -417,3 +419,21 @@ TEST_CASE("[UNetUDP]: bad packet number","[unetudp][badnumber]")
REQUIRE( ui->getValue(8) == 160 ); REQUIRE( ui->getValue(8) == 160 );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TEST_CASE("[UNetUDP]: switching channels","[unetudp][chswitch]")
{
InitTest();
UniSetUDP::UDPMessage pack;
pack.addAData(8,70);
send(pack);
msleep(120);
REQUIRE( ui->getValue(8) == 70 );
// К сожалению в текущей реализации тестов
// обмена по второму каналу нет
// поэтому проверить переключение нет возможности
// остаётся только проверить, что мы не "ушли" с первого канала
// т.к. на втором нет связи и мы не должны на него переключаться
msleep(recvTimeout*2);
REQUIRE( ui->getValue(node1_numchannel_as) == 1 );
}
// -----------------------------------------------------------------------------
...@@ -32,11 +32,11 @@ ...@@ -32,11 +32,11 @@
</settings> </settings>
<ObjectsMap idfromfile="1"> <ObjectsMap idfromfile="1">
<nodes port="2809" unet_broadcast_ip="127.255.255.255"> <nodes port="2809" unet_broadcast_ip="127.255.255.255" unet_broadcast_ip2="badip">
<item id="3000" ip="127.0.0.1" name="localhost" textname="Локальный узел" unet_ignore="0" unet_port="3000"/> <item id="3000" ip="127.0.0.1" name="localhost" textname="Локальный узел" unet_ignore="0" unet_port="3000"/>
<item id="3001" ip="127.0.0.1" name="localhost1" textname="Локальный узел" unet_ignore="1" unet_port="3001"/> <item id="3001" ip="127.0.0.1" name="localhost1" textname="Локальный узел" unet_ignore="1" unet_port="3001"/>
<item id="3002" ip="192.168.56.10" name="Node1" textname="Node1" unet_ignore="0" unet_ip="192.168.56.255" unet_respond_id="Node1_Respond_S" unet_respond_invert="1"/> <item id="3002" ip="192.168.56.10" name="Node1" textname="Node1" unet_ignore="0" unet_ip="192.168.56.255" unet_respond_id="Node1_Respond_S" unet_respond_invert="1"/>
<item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_ip="192.168.56.255" unet_respond_id="Node2_Respond_S" unet_lostpackets_id="Node2_LostPackets_AS"/> <item id="3003" ip="192.168.56.11" name="Node2" textname="Node2" unet_ignore="0" unet_ip="192.168.56.255" unet_respond_id="Node2_Respond_S" unet_lostpackets_id="Node2_LostPackets_AS" unet_numchannel_id="Node2_NumChannel_AS"/>
</nodes> </nodes>
<!-- ************************ Датчики ********************** --> <!-- ************************ Датчики ********************** -->
<sensors name="Sensors"> <sensors name="Sensors">
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
<item id="11" iotype="DI" name="DI4_S" textname="DI sensor 4"/> <item id="11" iotype="DI" name="DI4_S" textname="DI sensor 4"/>
<item id="12" iotype="DI" name="Node2_Respond_S" textname="Node2 respond"/> <item id="12" iotype="DI" name="Node2_Respond_S" textname="Node2 respond"/>
<item id="13" iotype="AI" name="Node2_LostPackets_AS" textname="Node2 lost packets"/> <item id="13" iotype="AI" name="Node2_LostPackets_AS" textname="Node2 lost packets"/>
<item id="14" iotype="AI" name="Node2_NumChannel_AS" textname="Node2 num channel"/>
</sensors> </sensors>
<thresholds name="thresholds"/> <thresholds name="thresholds"/>
......
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