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

Добавил поддержку пороговых датчиков для процессов обмена по Modbus(RTU|TCP)

parent 5589b01c
......@@ -8,7 +8,7 @@
Name: libuniset2
Version: 2.0
Release: alt0.5
Release: alt0.6
Summary: UniSet - library for building distributed industrial control systems
......@@ -333,6 +333,10 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
%exclude %_pkgconfigdir/libUniSet2.pc
%changelog
* Sun Feb 02 2014 Pavel Vainerman <pv@altlinux.ru> 2.0-alt0.6
- add thresholds processing for ModbusMaster (TCP and RTU)
- minor fixes
* Fri Jan 31 2014 Pavel Vainerman <pv@altlinux.ru> 2.0-alt0.5
- minor fixes
- test build
......
......@@ -228,6 +228,8 @@
<item id="58" iotype="AO" name="Lamp58_C" textname="Lamp 58" rrd="1" rrd1_ds="GAUGE:20:U:U"/>
<item id="62" iotype="AI" name="LogLevel_S" textname="LogLevel control"/>
<item id="63" iotype="AI" name="SVU_AskCount_AS" textname="svu asl count"/>
<item id="64" iotype="AI" name="AI64_AS" textname="AI64" mbaddr="0x01" mbfunc="0x03" mbreg="64" mbtype="rtu" rs="5"/>
<item id="65" iotype="DI" name="D65_S" textname="D65" threshold_aid="AI64_AS" lowlimit="3" hilimit="5" threshold_invert="1" rs="5" />
</sensors>
<thresholds name="thresholds">
<sensor iotype="AI" name="AI_AS">
......
......@@ -272,7 +272,10 @@ void IOControl::execute()
// init iterators
for( IOMap::iterator it=iomap.begin(); it!=iomap.end(); ++it )
{
shm->initIterator(it->ioit);
shm->initIterator(it->t_ait);
}
readconf_ok = true; // т.к. waitSM() уже был...
}
......
......@@ -259,10 +259,10 @@ int main(int argc, char* argv[])
if( verb )
printf( "write: ch=%d val=%d\n",chan[k],val);
if( comedi_dio_write(card, subdev, chan[k], val) < 0)
if( comedi_dio_write(card, subdev, chan[k], val) < 0)
{
fprintf(stderr,"can't write 1 to channel %d. (%d) %s\n",k,errno,strerror(errno));
exret = EXIT_FAILURE;
fprintf(stderr,"can't write 1 to channel %u. (%d) %s\n",k,errno,strerror(errno));
exret = EXIT_FAILURE;
}
}
......
......@@ -278,13 +278,13 @@ MBExchange::DeviceType MBExchange::getDeviceType( const std::string& dtype )
if( dtype == "mtr" || dtype == "MTR" )
return dtMTR;
if( dtype == "rtu" || dtype == "RTU" )
return dtRTU;
if( dtype == "rtu188" || dtype == "RTU188" )
return dtRTU188;
return dtUnknown;
}
// ------------------------------------------------------------------------------------------
......@@ -300,9 +300,18 @@ void MBExchange::initIterators()
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
for( PList::iterator it2=it->second->slst.begin();it2!=it->second->slst.end(); ++it2 )
{
shm->initIterator(it2->ioit);
shm->initIterator(it2->t_ait);
}
}
}
for( MBExchange::ThresholdList::iterator t=thrlist.begin(); t!=thrlist.end(); ++t )
{
shm->initIterator(t->ioit);
shm->initIterator(t->t_ait);
}
}
// -----------------------------------------------------------------------------
bool MBExchange::checkUpdateSM( bool wrFunc, long mdev )
......@@ -1739,7 +1748,6 @@ MBExchange::RegInfo* MBExchange::addReg( RegMap& mp, RegID id, ModbusRTU::Modbus
<< "(id=" << id << ")"
<< " already added for " << (*it->second)
<< " Ignore register params for " << xmlit.getProp("name") << " ..." << endl;
it->second->rit = it;
return it->second;
......@@ -1790,6 +1798,17 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
if( !IOBase::initItem(&p,it,shm,&dlog,myname) )
return false;
// проверяем не пороговый ли это датчик (т.е. не связанный с обменом)
// тогда заносим его в отдельный список
if( p.t_ai != DefaultObjectId )
{
// испольуем конструктор копирования, чтобы сформировать IOBase
// через преобразование указателя к базовому классу
IOBase b( *(static_cast<IOBase*>(&p)) );
thrlist.push_back(b);
return true;
}
if( it.getIntProp(prop_prefix + "rawdata") )
{
p.cal.minRaw = 0;
......@@ -1811,7 +1830,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
return false;
}
}
string sbit(it.getProp(prop_prefix + "nbit"));
if( !sbit.empty() )
{
......@@ -1823,7 +1842,7 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
return false;
}
}
if( p.nbit > 0 &&
( p.stype == UniversalIO::AI ||
p.stype == UniversalIO::AO ) )
......@@ -2724,20 +2743,14 @@ void MBExchange::poll()
updateSM();
// check thresholds
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
for( MBExchange::ThresholdList::iterator t=thrlist.begin(); t!=thrlist.end(); ++t )
{
RTUDevice* d(it1->second);
for( MBExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
if( !checkProcActive() )
return;
if( !checkProcActive() )
return;
RegInfo* r(it->second);
for( PList::iterator i=r->slst.begin(); i!=r->slst.end(); ++i )
IOBase::processingThreshold( &(*i),shm,force);
}
IOBase::processingThreshold(&(*t),shm,force);
}
if( trReopen.hi(allNotRespond) )
ptReopen.reset();
......
......@@ -30,7 +30,7 @@ class MBExchange:
MBExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0,
const std::string& prefix="mb" );
virtual ~MBExchange();
/*! глобальная функция для вывода help-а */
static void help_print( int argc, const char* const* argv );
......@@ -47,7 +47,7 @@ class MBExchange:
};
friend std::ostream& operator<<( std::ostream& os, const ExchangeMode& em );
enum DeviceType
{
dtUnknown, /*!< неизвестный */
......@@ -70,7 +70,7 @@ class MBExchange:
VTypes::VType vType; /*!< type of value */
short rnum; /*!< count of registers */
short nbyte; /*!< byte number (1-2) */
RSProperty():
nbit(-1),vType(VTypes::vtUnknown),
rnum(VTypes::wsize(VTypes::vtUnknown)),
......@@ -112,11 +112,11 @@ class MBExchange:
// only for MTR
MTR::MTRType mtrType; /*!< тип регистра (согласно спецификации на MTR) */
// optimization
int q_num; /*!< number in query */
int q_count; /*!< count registers for query */
RegMap::iterator rit;
// начальная инициалиазция для "записываемых" регистров
......@@ -153,7 +153,7 @@ class MBExchange:
{
resp_trTimeout.change(false);
}
bool respnond;
ModbusRTU::ModbusAddr mbaddr; /*!< адрес устройства */
RegMap regmap;
......@@ -182,7 +182,7 @@ class MBExchange:
};
friend std::ostream& operator<<( std::ostream& os, RTUDevice& d );
typedef std::map<ModbusRTU::ModbusAddr,RTUDevice*> RTUDeviceMap;
friend std::ostream& operator<<( std::ostream& os, RTUDeviceMap& d );
......@@ -278,7 +278,7 @@ class MBExchange:
std::string s_fvalue;
SMInterface* shm;
bool initPause;
UniSetTypes::uniset_rwmutex mutex_start;
......@@ -317,12 +317,17 @@ class MBExchange:
PassiveTimer ptTimeout;
bool pollActivated;
int recv_timeout;
int aftersend_pause;
PassiveTimer ptReopen; /*!< таймер для переоткрытия соединения */
Trigger trReopen;
// т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
// и отдельно его проверяем потом
typedef std::list<IOBase> ThresholdList;
ThresholdList thrlist;
private:
MBExchange();
......
......@@ -204,14 +204,14 @@ void RTUExchange::poll()
bool allNotRespond = true;
ComPort::Speed s = mbrtu->getSpeed();
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
{
RTUDevice* d(it1->second);
if( d->mode_id != DefaultObjectId && d->mode == emSkipExchange )
continue;
if( d->speed != s )
{
s = d->speed;
......@@ -236,7 +236,7 @@ void RTUExchange::poll()
d->resp_real = true;
}
catch( ModbusRTU::mbException& ex )
{
{
if( d->resp_real )
{
dlog3 << myname << "(poll): FAILED ask addr=" << ModbusRTU::addr2str(d->mbaddr)
......@@ -290,19 +290,16 @@ void RTUExchange::poll()
// update SharedMemory...
updateSM();
// check thresholds
for( MBExchange::RTUDeviceMap::iterator it1=rmap.begin(); it1!=rmap.end(); ++it1 )
for( MBExchange::ThresholdList::iterator t=thrlist.begin(); t!=thrlist.end(); ++t )
{
RTUDevice* d(it1->second);
for( RTUExchange::RegMap::iterator it=d->regmap.begin(); it!=d->regmap.end(); ++it )
{
RegInfo* r(it->second);
for( PList::iterator i=r->slst.begin(); i!=r->slst.end(); ++i )
IOBase::processingThreshold( &(*i),shm,force);
}
if( !checkProcActive() )
return;
IOBase::processingThreshold(&(*t),shm,force);
}
if( trReopen.hi(allNotRespond) )
ptReopen.reset();
......@@ -345,14 +342,14 @@ bool RTUExchange::initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniX
{
if( !MBExchange::initDeviceInfo(m,a,it) )
return false;
RTUDeviceMap::iterator d = m.find(a);
if( d == m.end() )
{
dwarn << myname << "(initDeviceInfo): not found device for addr=" << ModbusRTU::addr2str(a) << endl;
return false;
}
string s = it.getProp("speed");
if( !s.empty() )
{
......
......@@ -16,7 +16,7 @@ class RTUExchange:
RTUExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID,
SharedMemory* ic=0, const std::string& prefix="rs" );
virtual ~RTUExchange();
/*! глобальная функция для инициализации объекта */
static RTUExchange* init_rtuexchange( int argc, const char* const* argv,
UniSetTypes::ObjectId shmID, SharedMemory* ic=0,
......
#!/bin/sh
./uniset2-start.sh -f ./uniset2-mbtcpmaster \
./uniset-start.sh -f ./uniset2-mbtcpmaster \
--confile test.xml \
--mbtcp-name MBMaster1 \
--smemory-id SharedMemory \
......
......@@ -12,6 +12,7 @@ using namespace UniSetExtensions;
SMDBServer::SMDBServer( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, SharedMemory* ic,
const string& prefix ):
DBServer_MySQL(objId),
aiignore(false),
prefix(prefix)
{
if( objId == DefaultObjectId )
......
......@@ -64,10 +64,10 @@ int main( int argc, const char** argv )
SystemMessage sm(SystemMessage::StartUp);
act.broadcast( sm.transport_msg() );
ulog.ebug::ANY) << "\n\n\n";
ulog.ebug::ANY] << "(main): -------------- SMDBServer START -------------------------\n\n";
dlog(Debug::ANY) << "\n\n\n";
dlog[Debug::ANY] << "(main): -------------- SMDBServer START -------------------------\n\n";
ulog << "\n\n\n";
ulog << "(main): -------------- SMDBServer START -------------------------\n\n";
dlog << "\n\n\n";
dlog << "(main): -------------- SMDBServer START -------------------------\n\n";
act.run(false);
return 0;
}
......
......@@ -11,9 +11,9 @@
#include "IOController.h"
#include "SMInterface.h"
// -----------------------------------------------------------------------------
static const int DefaultSubdev = -1;
static const int DefaultSubdev = -1;
static const int DefaultChannel = -1;
static const int NoSafety = -1;
static const int NoSafety = -1;
// -----------------------------------------------------------------------------
/*! Информация о входе/выходе */
struct IOBase
......@@ -72,30 +72,31 @@ static const int NoSafety = -1;
bool ignore; /*!< игнорировать при опросе */
bool invert; /*!< инвертированная логика */
bool noprecision;
PassiveTimer ptJar; /*!< таймер на дребезг */
PassiveTimer ptOnDelay; /*!< задержка на срабатывание */
PassiveTimer ptOffDelay; /*!< задержка на отпускание */
bool jar_pause;
Trigger trOnDelay;
Trigger trOffDelay;
Trigger trJar;
bool jar_state; /*!< значение для фильтра дребезга */
bool ondelay_state; /*!< значение для задержки включения */
bool offdelay_state; /*!< значение для задержки отключения */
// Порог
UniSetTypes::ObjectId t_ai; /*!< если данный датчик дискретный,
и является пороговым, то в данном поле
хранится идентификатор аналогового датчика
с которым он связан */
IONotifyController_i::ThresholdInfo ti;
IOController::IOStateList::iterator t_ait; // итератор для аналогового датчика
// Работа по фронтам сигнала
enum FrontType
{
{
ftUnknown,
ft01, // срабатывание на переход "0-->1"
ft10 // срабатывание на переход "1-->0"
......@@ -105,10 +106,10 @@ static const int NoSafety = -1;
FrontType front_type;
bool front_prev_state;
bool front_state;
IOController::IOStateList::iterator ioit;
UniSetTypes::uniset_rwmutex val_lock; /*!< блокировка на время "работы" со значением */
friend std::ostream& operator<<(std::ostream& os, IOBase& inf );
static void processingFasAI( IOBase* it, float new_val, SMInterface* shm, bool force );
......
......@@ -338,7 +338,7 @@ float IOBase::processingFasAO( IOBase* it, SMInterface* shm, bool force )
return ( fval / pow10(it->cal.precision) );
}
}
return val;
}
// -----------------------------------------------------------------------------
......@@ -346,8 +346,8 @@ void IOBase::processingThreshold( IOBase* it, SMInterface* shm, bool force )
{
if( it->t_ai == DefaultObjectId )
return;
long val = shm->localGetValue(it->ioit,it->t_ai);
long val = shm->localGetValue(it->t_ait,it->t_ai);
bool set = it->value ? true : false;
// cout << "val=" << val << " set=" << set << endl;
......@@ -462,7 +462,7 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
b->f_median = false;
b->f_ls = false;
b->f_filter_iir = false;
shm->initIterator(b->ioit);
if( b->stype == UniversalIO::AI || b->stype == UniversalIO::AO )
......@@ -480,7 +480,7 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
int f_iir = it.getIntProp("iir_thr");
float f_iir_coeff_prev = def_iir_coeff_prev;
float f_iir_coeff_new = def_iir_coeff_new;
if( f_median > 0 )
{
f_size = f_median;
......@@ -493,7 +493,7 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
if( !it.getProp("filtersize").empty() )
f_size = it.getPIntProp("filtersize",def_filtersize);
}
if( !it.getProp("filterT").empty() )
{
f_T = atof(it.getProp("filterT").c_str());
......@@ -547,6 +547,7 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm,
b->ti.lowlimit = it.getIntProp("lowlimit");
b->ti.hilimit = it.getIntProp("hilimit");
b->ti.invert = it.getIntProp("threshold_invert");
shm->initIterator(b->t_ait);
}
}
......
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