Commit 2da0b071 authored by Pavel Vainerman's avatar Pavel Vainerman

Внёс два новых типа данных VTypes::I2 и VTypes::U2.

Встроил обработку "многорегистровых"(многословных) данных в MBSlave. Теперь по MBSlave умеет передавать int,usigned int,float и т.п. (VTypes).
parent 0119af6a
......@@ -2,8 +2,8 @@
%define oname uniset
Name: libuniset
Version: 0.98
Release: eter9
Version: 0.99
Release: eter2
Summary: UniSet - library for building distributed industrial control systems
License: GPL
Group: Development/C++
......@@ -184,6 +184,9 @@ rm -f %buildroot%_libdir/*.la
%exclude %_pkgconfigdir/libUniSet.pc
%changelog
* Tue Sep 14 2010 Pavel Vainerman <pv@altlinux.ru> 0.99-eter1
- test UDP build
* Tue Sep 07 2010 Evgeny Sinelnikov <sin@altlinux.ru> 0.98-eter9
- Build for Sisyphus Etersoft addon:
commit fc7fb2eefaf900088d7e6583df440c914aeb9560
......
......@@ -150,7 +150,13 @@
<item name="DumpSensor6_S" textname="alarm dumpm sensor 6" a2="1" node="" iotype="DI" priority="Medium"/>
<item name="DumpSensor7_S" textname="alarm dumpm sensor 7" a2="1" node="" iotype="DI" priority="Medium"/>
<item name="DumpSensor8_S" textname="alarm dumpm sensor 8" a2="1" node="" iotype="DI" priority="Medium"/>
<item name="MB1_AS" textname="Analog input" node="" iotype="AI" default="-655360" priority="Medium"
mbtcp="2" mbtype="rtu" mbaddr="0x01" mbreg="0x12" mb_vtype="I2"/>
<item name="MB2_AS" textname="Analog input" node="" iotype="AI" default="6553604" priority="Medium"
mbtcp="2" mbtype="rtu" mbaddr="0x01" mbreg="0x14" mb_vtype="U2"/>
<item name="MB3_AS" textname="Analog input" node="" iotype="AI" default="65536045" priority="Medium"
mbtcp="2" mbtype="rtu" mbaddr="0x01" mbreg="0x17" mb_vtype="F2"/>
</sensors>
<thresholds name="thresholds">
......
......@@ -31,8 +31,6 @@ force(false),
mbregFromID(false),
prefix(prefix)
{
cout << "$Id: MBSlave.cc,v 1.1 2009/01/11 19:08:45 vpashka Exp $" << endl;
if( objId == DefaultObjectId )
throw UniSetTypes::SystemError("(MBSlave): objId=-1?!! Use --mbs-name" );
......@@ -717,14 +715,12 @@ bool MBSlave::initItem( UniXML_iterator& it )
if( stype.empty() )
stype = it.getProp("iotype");
if( stype == "AI" )
p.stype = UniversalIO::AnalogInput;
else if ( stype == "DI" )
p.stype = UniversalIO::DigitalInput;
else if ( stype == "AO" )
p.stype = UniversalIO::AnalogOutput;
else if ( stype == "DO" )
p.stype = UniversalIO::DigitalOutput;
p.stype = UniSetTypes::getIOType(stype);
if( p.stype == UniversalIO::UnknownIOType )
{
dlog[Debug::CRIT] << myname << "(initItem): Unknown 'iotype' or 'mb_iotype' for " << it.getProp("name") << endl;
return false;
}
p.amode = MBSlave::amRW;
string am(it.getProp("mb_accessmode"));
......@@ -735,7 +731,14 @@ bool MBSlave::initItem( UniXML_iterator& it )
string vt(it.getProp("mb_vtype"));
if( vt.empty() )
{
p.vtype = VTypes::vtUnknown;
p.wnum = 0;
iomap[p.mbreg] = p;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(initItem): add " << p << endl;
}
else
{
VTypes::VType v(VTypes::str2type(vt));
......@@ -748,12 +751,16 @@ bool MBSlave::initItem( UniXML_iterator& it )
return false;
}
p.vtype = v;
p.wnum = 0;
for( int i=0; i<VTypes::wsize(p.vtype); i++ )
{
p.mbreg += i;
p.wnum+= i;
iomap[p.mbreg] = p;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(initItem): add " << p << endl;
}
}
iomap[p.mbreg] = p;
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(initItem): add " << p << endl;
return true;
}
......@@ -824,6 +831,7 @@ std::ostream& operator<<( std::ostream& os, MBSlave::IOProperty& p )
os << " reg=" << ModbusRTU::dat2str(p.mbreg)
<< " sid=" << p.si.id
<< " stype=" << p.stype
<< " wnum=" << p.wnum
<< " safety=" << p.safety
<< " invert=" << p.invert;
......@@ -1076,14 +1084,54 @@ ModbusRTU::mbErrCode MBSlave::real_write( ModbusRTU::ModbusData reg,
return ModbusRTU::erTimeOut;
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_read( ModbusRTU::ModbusData reg,
ModbusRTU::ModbusData& val )
ModbusRTU::mbErrCode MBSlave::much_real_read( ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int count )
{
if( dlog.debugging(Debug::INFO) )
{
dlog[Debug::INFO] << myname << "(mush_real_read): read mbID="
<< ModbusRTU::dat2str(reg) << " count=" << count << endl;
}
IOMap::iterator it = iomap.find(reg);
if( it == iomap.end() )
return ModbusRTU::erBadDataAddress;
int i=0;
ModbusRTU::ModbusData val=0;
for( ; (it!=iomap.end()) && (i<count); it++,i++,reg++ )
{
val=0;
// если регистры идут не подряд, то просто вернём ноль
if( it->first == reg )
real_read_it(it,reg,val);
dat[i] = val;
}
return ModbusRTU::erNoError;
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_read( ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val )
{
if( dlog.debugging(Debug::INFO) )
{
dlog[Debug::INFO] << myname << "(real_read): read mbID="
<< ModbusRTU::dat2str(reg) << endl;
}
IOMap::iterator it = iomap.find(reg);
if( it == iomap.end() )
return ModbusRTU::erBadDataAddress;
return real_read_it(it,reg,val);
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::real_read_it( IOMap::iterator& it, ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val )
{
try
{
if( dlog.debugging(Debug::INFO) )
{
dlog[Debug::INFO] << myname << "(real_read): read mbID="
dlog[Debug::INFO] << myname << "(real_read_it): read mbID="
<< ModbusRTU::dat2str(reg) << endl;
}
......@@ -1105,7 +1153,52 @@ ModbusRTU::mbErrCode MBSlave::real_read( ModbusRTU::ModbusData reg,
else if( p->stype == UniversalIO::AnalogInput ||
p->stype == UniversalIO::AnalogOutput )
{
val = IOBase::processingAsAO(p,shm,force);
if( p->vtype == VTypes::vtUnknown )
{
val = IOBase::processingAsAO(p,shm,force);
}
if( p->vtype == VTypes::vtF2 )
{
float f = IOBase::processingFasAO(p,shm,force);
VTypes::F2 f2(f);
// оптимизируем и проверку не делаем
// считая, что при "загрузке" всё было правильно
// инициализировано
// if( p->wnum >=0 && p->wnum < f4.wsize()
val = f2.raw.v[p->wnum];
}
else if( p->vtype == VTypes::vtF4 )
{
float f = IOBase::processingFasAO(p,shm,force);
VTypes::F4 f4(f);
// оптимизируем и проверку не делаем
// считая, что при "загрузке" всё было правильно
// инициализировано
// if( p->wnum >=0 && p->wnum < f4.wsize()
val = f4.raw.v[p->wnum];
}
else if( p->vtype == VTypes::vtI2 )
{
long v = IOBase::processingAsAO(p,shm,force);
VTypes::I2 i2(v);
// оптимизируем и проверку не делаем
// считая, что при "загрузке" всё было правильно
// инициализировано
// if( p->wnum >=0 && p->wnum < i2.wsize()
val = i2.raw.v[p->wnum];
}
else if( p->vtype == VTypes::vtU2 )
{
unsigned long v = IOBase::processingAsAO(p,shm,force);
VTypes::U2 u2(v);
// оптимизируем и проверку не делаем
// считая, что при "загрузке" всё было правильно
// инициализировано
// if( p->wnum >=0 && p->wnum < u2.wsize()
val = u2.raw.v[p->wnum];
}
else
val = IOBase::processingAsAO(p,shm,force);
}
else
return ModbusRTU::erBadDataAddress;
......@@ -1115,29 +1208,29 @@ ModbusRTU::mbErrCode MBSlave::real_read( ModbusRTU::ModbusData reg,
}
catch( UniSetTypes::NameNotFound& ex )
{
dlog[Debug::WARN] << myname << "(real_read): " << ex << endl;
dlog[Debug::WARN] << myname << "(real_read_it): " << ex << endl;
return ModbusRTU::erBadDataAddress;
}
catch( UniSetTypes::OutOfRange& ex )
{
dlog[Debug::WARN] << myname << "(real_read): " << ex << endl;
dlog[Debug::WARN] << myname << "(real_read_it): " << ex << endl;
return ModbusRTU::erBadDataValue;
}
catch( Exception& ex )
{
if( pingOK )
dlog[Debug::CRIT] << myname << "(real_read): " << ex << endl;
dlog[Debug::CRIT] << myname << "(real_read_it): " << ex << endl;
}
catch( CORBA::SystemException& ex )
{
if( pingOK )
dlog[Debug::CRIT] << myname << "(real_read): CORBA::SystemException: "
dlog[Debug::CRIT] << myname << "(real_read_it): CORBA::SystemException: "
<< ex.NP_minorString() << endl;
}
catch(...)
{
if( pingOK )
dlog[Debug::CRIT] << myname << "(real_read) catch ..." << endl;
dlog[Debug::CRIT] << myname << "(real_read_it) catch ..." << endl;
}
pingOK = false;
......@@ -1162,15 +1255,27 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query,
else
reply.addData(0);
pingOK = true;
return ret;
}
// Фомирование ответа:
int num=0; // добавленное количество данных
ModbusRTU::ModbusData d = 0;
much_real_read(query.start,buf,query.count);
for( int i=0; i<query.count; i++ )
reply.addData( buf[i] );
/*
ModbusRTU::ModbusData* dat = new ModbusRTU::ModbusData[query.count];
ModbusRTU::ModbusData reg = query.start;
try
{
much_real_read(reg,dat,query.count);
}
catch(...){}
delete[] dat;
*/
/*
for( ; num<query.count; num++, reg++ )
{
ModbusRTU::mbErrCode ret = real_read(reg,d);
......@@ -1188,7 +1293,7 @@ mbErrCode MBSlave::readInputRegisters( ReadInputMessage& query,
<< "(readInputRegisters): query.count=" << (int)query.count
<< " > reply.count=" << (int)reply.count << endl;
}
*/
pingOK = true;
return ModbusRTU::erNoError;
}
......@@ -1276,6 +1381,10 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query,
}
// Фомирование ответа:
much_real_read(query.start,buf,query.count);
for( int i=0; i<query.count; i++ )
reply.addData( buf[i] );
/*
int num=0; // добавленное количество данных
ModbusRTU::ModbusData d = 0;
ModbusRTU::ModbusData reg = query.start;
......@@ -1287,7 +1396,7 @@ ModbusRTU::mbErrCode MBSlave::readInputStatus( ReadInputStatusMessage& query,
else
reply.addData(0);
}
*/
// Если мы в начале проверили, что запрос входит в разрешёный диапазон
// то теоретически этой ситуации возникнуть не может...
// if( reply.bcnt < query.count )
......
......@@ -19,6 +19,9 @@
#include "VTypes.h"
#include "ThreadCreator.h"
// -----------------------------------------------------------------------------
/*!
\todo Доделать многорегистровую запись (т.е. запись для vtype=[F2,F4,I2,I4,U2,U4]
*/
class MBSlave:
public UniSetObject_LT
{
......@@ -49,10 +52,12 @@ class MBSlave:
ModbusRTU::ModbusData mbreg; /*!< регистр */
AccessMode amode;
VTypes::VType vtype; /*!< type of value */
int wnum; /*!< номер слова (для типов с размеров больше 2х байт */
IOProperty():
mbreg(0),
vtype(VTypes::vtUnknown)
vtype(VTypes::vtUnknown),
wnum(0)
{}
friend std::ostream& operator<<( std::ostream& os, IOProperty& p );
......@@ -152,7 +157,8 @@ class MBSlave:
ModbusRTU::mbErrCode real_write( ModbusRTU::ModbusData reg, ModbusRTU::ModbusData val );
ModbusRTU::mbErrCode real_read( ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val );
ModbusRTU::mbErrCode much_real_read( ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, int count );
ModbusRTU::mbErrCode real_read_it( IOMap::iterator& it, ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val );
private:
MBSlave();
bool initPause;
......@@ -189,6 +195,8 @@ class MBSlave:
typedef std::map<int,std::string> FileList;
FileList flist;
std::string prefix;
ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET/2+1]; /*!< буфер для формирования ответов */
};
// -----------------------------------------------------------------------------
#endif // _MBSlave_H_
......
#!/bin/sh
uniset-start.sh -f ./uniset-mbslave --confile test.xml --dlog-add-levels info,crit,warn \
--mbs-name MBSlave1 \
--mbs-type TCP --mbs-inet-addr 127.0.0.1 --mbs-inet-port 2048 --mbs-my-addr 0x01 \
--mbs-askcount-id SVU_AskCount_AS \
--mbs-filter-field mbtcp --mbs-filter-value 2
\ No newline at end of file
......@@ -11,7 +11,7 @@ using namespace VTypes;
// --------------------------------------------------------------------------
static void print_help()
{
printf("Usage: vtconv TYPE[F2|F4] hex1 hex2 [hex3 hex4]\n");
printf("Usage: vtconv TYPE[F2|F4|I2|U2] hex1 hex2 [hex3 hex4]\n");
}
// --------------------------------------------------------------------------
int main( int argc, const char **argv )
......@@ -39,6 +39,26 @@ int main( int argc, const char **argv )
cout << "-------------" << endl << endl;
VTypes::I2 i2;
i2.raw.val = -6553004;
cout << "Example(I2): int=" << i2.raw.val
<< " regs:"
<< " v[0]=" << i2.raw.v[0]
<< " v[1]=" << i2.raw.v[1]
<< endl;
cout << "-------------" << endl << endl;
VTypes::U2 u2;
u2.raw.val = 655300400;
cout << "Example(U2): unsigned int=" << u2.raw.val
<< " regs:"
<< " v[0]=" << u2.raw.v[0]
<< " v[1]=" << u2.raw.v[1]
<< endl;
cout << "-------------" << endl << endl;
// return 0;
......@@ -81,6 +101,20 @@ int main( int argc, const char **argv )
<< " v[3]=" << v[3]
<< " --> (float) " << (float)f << endl;
}
else if( !strcmp(type,"I2") )
{
VTypes::I2 i(v,sizeof(v));
cout << "(I2): v[0]=" << v[0]
<< " v[1]=" << v[1]
<< " --> (int) " << (int)i << endl;
}
else if( !strcmp(type,"U2") )
{
VTypes::U2 i(v,sizeof(v));
cout << "(U2): v[0]=" << v[0]
<< " v[1]=" << v[1]
<< " --> (unsigned int) " << (unsigned int)i << endl;
}
else
{
cout << " Unknown type: " << type << endl;
......
......@@ -16,11 +16,13 @@ namespace VTypes
enum VType
{
vtUnknown,
vtF2, /*!< двойное слово (4 байта). В виде строки задаётся как \b "F2". */
vtF4, /*!< 8-х байтовое слово. В виде строки задаётся как \b "F4". */
vtF2, /*!< двойное слово float(4 байта). В виде строки задаётся как \b "F2". */
vtF4, /*!< 8-х байтовое слово (double). В виде строки задаётся как \b "F4". */
vtByte, /*!< байт. В виде строки задаётся как \b "byte". */
vtUnsigned, /*!< беззнаковое. В виде строки задаётся как \b "unsigned". */
vtSigned /*!< знаковое. В виде строки задаётся как \b "signed". */
vtUnsigned, /*!< беззнаковое целое (2 байта). В виде строки задаётся как \b "unsigned". */
vtSigned, /*!< знаковое целое (2 байта). В виде строки задаётся как \b "signed". */
vtI2, /*!< целое (4 байта). В виде строки задаётся как \b "I4".*/
vtU2 /*!< беззнаковое целое (4 байта). В виде строки задаётся как \b "U4".*/
};
std::ostream& operator<<( std::ostream& os, const VType& vt );
......@@ -203,6 +205,76 @@ namespace VTypes
signed short raw;
};
// --------------------------------------------------------------------------
class I2
{
public:
// ------------------------------------------
static const int i2Size=2;
/*! тип хранения в памяти */
typedef union
{
unsigned short v[i2Size];
int val; //
} I2mem;
// ------------------------------------------
// конструкторы на разные случаи...
I2(){ memset(raw.v,0,sizeof(raw.v)); }
I2( int v ){ raw.val = v; }
I2( const ModbusRTU::ModbusData* data, int size )
{
for( int i=0; i<wsize() && i<size; i++ )
raw.v[i] = data[i];
}
~I2(){}
// ------------------------------------------
/*! размер в словах */
static int wsize(){ return i2Size; }
/*! тип значения */
static VType type(){ return vtI2; }
// ------------------------------------------
operator int(){ return raw.val; }
I2mem raw;
};
// --------------------------------------------------------------------------
class U2
{
public:
// ------------------------------------------
static const int u2Size=2;
/*! тип хранения в памяти */
typedef union
{
unsigned short v[u2Size];
unsigned int val; //
} U2mem;
// ------------------------------------------
// конструкторы на разные случаи...
U2(){ memset(raw.v,0,sizeof(raw.v)); }
U2( unsigned int v ){ raw.val = v; }
U2( const ModbusRTU::ModbusData* data, int size )
{
for( int i=0; i<wsize() && i<size; i++ )
raw.v[i] = data[i];
}
~U2(){}
// ------------------------------------------
/*! размер в словах */
static int wsize(){ return u2Size; }
/*! тип значения */
static VType type(){ return vtU2; }
// ------------------------------------------
operator unsigned int(){ return raw.val; }
U2mem raw;
};
// --------------------------------------------------------------------------
} // end of namespace VTypes
// --------------------------------------------------------------------------
......
......@@ -26,6 +26,10 @@ VType str2type( const std::string s )
return vtUnsigned;
if( s == "Signed" || s == "signed" )
return vtSigned;
if( s == "I2" || s == "i2" )
return vtI2;
if( s == "U2" || s == "u2" )
return vtU2;
return vtUnknown;
}
......@@ -42,6 +46,10 @@ string type2str( VType t )
return "Unsigned";
if( t == vtSigned )
return "Signed";
if( t == vtI2 )
return "I2";
if( t == vtU2 )
return "U2";
return "vtUnknown";
}
......@@ -58,6 +66,10 @@ int wsize( VType t )
return Unsigned::wsize();
if( t == vtSigned )
return Signed::wsize();
if( t == vtI2 )
return I2::wsize();
if( t == vtU2 )
return U2::wsize();
return 1;
}
......
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