Commit 8744a63f authored by Pavel Vainerman's avatar Pavel Vainerman

(IOBase): ввёл флаг rawdata, для работы с VTypes::F4 "без преобразования",

а так же для отключения "одним махом".. Calibraction,precision и т.п.
parent 30790f2d
......@@ -1882,16 +1882,6 @@ bool MBExchange::initRSProperty( RSProperty& p, UniXML_iterator& it )
return true;
}
if( IOBase::initIntProp(it,"rawdata",prefix,false) )
{
p.cal.minRaw = 0;
p.cal.maxRaw = 0;
p.cal.minCal = 0;
p.cal.maxCal = 0;
p.cal.precision = 0;
p.cdiagram = 0;
}
string sbit(IOBase::initProp(it,"nbit",prefix,false));
if( !sbit.empty() )
{
......
......@@ -812,16 +812,6 @@ bool MBSlave::initItem( UniXML_iterator& it )
if( !IOBase::initItem( static_cast<IOBase*>(&p),it,shm,prop_prefix,false,&dlog,myname) )
return false;
if( IOBase::initIntProp(it,"rawdata",prefix,false) )
{
p.cal.minRaw = 0;
p.cal.maxRaw = 0;
p.cal.minCal = 0;
p.cal.maxCal = 0;
p.cal.precision = 0;
p.cdiagram = 0;
}
if( mbregFromID )
p.mbreg = p.si.id;
else
......
......@@ -49,13 +49,15 @@ class MBSlave:
ModbusRTU::ModbusData mbreg; /*!< регистр */
AccessMode amode;
VTypes::VType vtype; /*!< type of value */
int wnum; /*!< номер слова (для типов с размеров больше 2х байт */
int wnum; /*!< номер слова (для типов с размеров больше 2х байт */
bool rawdata; /*!< флаг, что в SM просто сохраняются 4-байта (актуально для типа F4)*/
IOProperty():
mbreg(0),
amode(amRW),
vtype(VTypes::vtUnknown),
wnum(0)
wnum(0),
rawdata(false)
{}
friend std::ostream& operator<<( std::ostream& os, IOProperty& p );
......
......@@ -146,6 +146,7 @@
<item id="2009" default="250000" precision="5" mbs="1" mbreg="114" iotype="AI" vtype="F4" name="TestVtype9" textname="Тестовый регистр для проверки vtype"/>
<item default="-100" id="2011" mbs="1" mbreg="118" iotype="AI" vtype="signed" name="TestVtype11" textname="Тестовый регистр для проверки vtype"/>
<item default="65534" id="2012" mbs="1" mbreg="119" iotype="AI" vtype="unsigned" name="TestVtype12" textname="Тестовый регистр для проверки vtype"/>
<item id="2013" rawdata="1" mbs="1" mbreg="120" iotype="AI" vtype="F4" name="TestVtype9" textname="Тестовый регистр для проверки vtype"/>
<item id="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/>
......
......@@ -629,7 +629,7 @@ static void test_write10_U2r( unsigned int val )
REQUIRE( ret.quant == U2r::wsize() );
REQUIRE( (unsigned int)ui->getValue(2004) == val );
}
static void test_write10_F2( float val )
static void test_write10_F2( const float& val )
{
using namespace VTypes;
ModbusRTU::ModbusData tREG = 110;
......@@ -649,7 +649,7 @@ static void test_write10_F2( float val )
REQUIRE( fval == val );
}
static void test_write10_F2r( float val )
static void test_write10_F2r( const float& val )
{
using namespace VTypes;
ModbusRTU::ModbusData tREG = 112;
......@@ -670,6 +670,53 @@ static void test_write10_F2r( float val )
REQUIRE( fval == val );
}
static void test_write10_F4raw( const float& val )
{
using namespace VTypes;
ModbusRTU::ModbusData tREG = 120;
ModbusRTU::WriteOutputMessage msg(slaveaddr,tREG);
F4 tmp(val);
msg.addData( tmp.raw.v[0] );
msg.addData( tmp.raw.v[1] );
msg.addData( tmp.raw.v[2] );
msg.addData( tmp.raw.v[3] );
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == F4::wsize() );
IOController_i::SensorInfo si;
si.id = 2013;
si.node = conf->getLocalNode();
long raw = ui->getValue(si.id);
float fval = 0;
memcpy( &fval,&raw,std::min(sizeof(fval),sizeof(raw)) );
REQUIRE( fval == val );
}
static void test_write10_F4prec( const float& val )
{
using namespace VTypes;
ModbusRTU::ModbusData tREG = 114;
ModbusRTU::WriteOutputMessage msg(slaveaddr,tREG);
F4 tmp(val);
msg.addData( tmp.raw.v[0] );
msg.addData( tmp.raw.v[1] );
msg.addData( tmp.raw.v[2] );
msg.addData( tmp.raw.v[3] );
ModbusRTU::WriteOutputRetMessage ret = mb->write10(msg);
REQUIRE( ret.start == tREG );
REQUIRE( ret.quant == F4::wsize() );
IOController_i::SensorInfo si;
si.id = 2009;
si.node = conf->getLocalNode();
IOController_i::CalibrateInfo cal = ui->getCalibrateInfo(si);
float fval = (float)ui->getValue(si.id) / pow10(cal.precision);
REQUIRE( fval == val );
}
TEST_CASE("Write(0x10): vtypes..","[modbus][mbslave][mbtcpslave]")
{
using namespace VTypes;
......@@ -711,8 +758,17 @@ TEST_CASE("Write(0x10): vtypes..","[modbus][mbslave][mbtcpslave]")
test_write10_F2r(0);
test_write10_F2r(100000.23);
}
SECTION("Test: write vtype 'F4'")
SECTION("Test: write vtype 'F4'(raw)")
{
test_write10_F4raw(numeric_limits<float>::max());
test_write10_F4raw(0);
test_write10_F4raw(numeric_limits<float>::min());
}
SECTION("Test: write vtype 'F4'(precision)")
{
test_write10_F4prec(15.55555);
test_write10_F4prec(0);
test_write10_F4prec(-15.00001);
}
}
......@@ -746,3 +802,8 @@ TEST_CASE("(0x66): file transfer")
}
#endif
TEST_CASE("access mode","[modbus][mbslvae][mbtcpslave]")
{
}
\ No newline at end of file
......@@ -49,7 +49,8 @@ static const int NoSafety = -1;
front(false),
front_type(ftUnknown),
front_prev_state(false),
front_state(false)
front_state(false),
rawdata(false)
{
si.id = UniSetTypes::DefaultObjectId;
si.node = UniSetTypes::DefaultObjectId;
......@@ -119,6 +120,8 @@ static const int NoSafety = -1;
bool front_prev_state;
bool front_state;
bool rawdata; // флаг для сохранения данный в таком виде в каком они пришли (4байта просто копируются в long). Актуально для Vtypes::F4.
IOController::IOStateList::iterator ioit;
UniSetTypes::uniset_rwmutex val_lock; /*!< блокировка на время "работы" со значением */
......
......@@ -50,7 +50,7 @@ namespace VTypes
// конструкторы на разные случаи...
F2(){ memset(raw.v,0,sizeof(raw.v)); }
F2( float f ){ raw.val = f; }
F2( const float& f ){ raw.val = f; }
F2( const ModbusRTU::ModbusData* data, int size )
{
for( int i=0; i<wsize() && i<size; i++ )
......@@ -80,7 +80,7 @@ namespace VTypes
// конструкторы на разные случаи...
F2r(){}
F2r( float f ):F2(f)
F2r( const float& f ):F2(f)
{
raw_backorder = raw;
std::swap(raw_backorder.v[0],raw_backorder.v[1]);
......@@ -112,7 +112,7 @@ namespace VTypes
// конструкторы на разные случаи...
F4(){ memset(raw.v,0,sizeof(raw.v)); }
F4( float f ){ raw.val = f; }
F4( const float& f ){ raw.val = f; }
F4( const ModbusRTU::ModbusData* data, int size )
{
for( int i=0; i<wsize() && i<size; i++ )
......@@ -150,7 +150,7 @@ namespace VTypes
Byte(){ raw.w = 0; }
Byte( unsigned char b1, unsigned char b2 ){ raw.b[0]=b1; raw.b[1]=b2; }
Byte( const long val )
Byte( const long& val )
{
raw.w = val;
}
......@@ -182,7 +182,7 @@ namespace VTypes
// конструкторы на разные случаи...
Unsigned():raw(0){}
Unsigned( const long val )
Unsigned( const long& val )
{
raw = val;
}
......@@ -212,7 +212,7 @@ namespace VTypes
// конструкторы на разные случаи...
Signed():raw(0){}
Signed( const long val )
Signed( const long& val )
{
raw = val;
}
......@@ -275,7 +275,7 @@ namespace VTypes
public:
I2r(){}
I2r( int v ):I2(v)
I2r( const int v ):I2(v)
{
raw_backorder = raw;
std::swap(raw_backorder.v[0],raw_backorder.v[1]);
......
......@@ -136,27 +136,29 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force
val = it->df.filterRC(val);
}
if( it->cdiagram ) // задана специальная калибровочная диаграмма
{
if( it->craw != val )
{
it->craw = val;
val = it->cdiagram->getValue(val);
it->cprev = val;
}
else
val = it->cprev; // просто передаём предыдущее значение
}
else
{
IOController_i::CalibrateInfo* cal( &(it->cal) );
if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка
val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,true);
}
if( !it->noprecision && it->cal.precision > 0 )
val *= lround(pow10(it->cal.precision));
if( !it->rawdata )
{
if( it->cdiagram ) // задана специальная калибровочная диаграмма
{
if( it->craw != val )
{
it->craw = val;
val = it->cdiagram->getValue(val);
it->cprev = val;
}
else
val = it->cprev; // просто передаём предыдущее значение
}
else
{
IOController_i::CalibrateInfo* cal( &(it->cal) );
if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка
val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,true);
}
if( !it->noprecision && it->cal.precision > 0 )
val *= lround(pow10(it->cal.precision));
}
// если предыдущее значение "обрыв",
// то сбрасываем признак
{
......@@ -176,7 +178,12 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for
{
long val = lroundf(fval);
if( it->cal.precision > 0 )
if( it->rawdata )
{
val = 0;
memcpy(&val,&fval, std::min(sizeof(val),sizeof(fval)));
}
else if( it->cal.precision > 0 )
val = lroundf( fval * pow10(it->cal.precision) );
// проверка на обрыв
......@@ -199,9 +206,12 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for
val = it->df.filterRC(val);
}
IOController_i::CalibrateInfo* cal( &(it->cal) );
if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка
val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,true);
if( !it->rawdata )
{
IOController_i::CalibrateInfo* cal( &(it->cal) );
if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка
val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,true);
}
}
// если предыдущее значение "обрыв",
......@@ -252,6 +262,9 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force )
it->value = val;
}
if( it->rawdata )
return val;
if( it->stype == UniversalIO::AO ||
it->stype == UniversalIO::AI )
{
......@@ -309,6 +322,13 @@ float IOBase::processingFasAO( IOBase* it, SMInterface* shm, bool force )
it->value = val;
}
if( it->rawdata )
{
float fval=0;
memcpy(&fval,&val, std::min(sizeof(val),sizeof(fval)));
return fval;
}
if( it->stype == UniversalIO::AO ||
it->stype == UniversalIO::AI )
{
......@@ -437,6 +457,7 @@ bool IOBase::initItem( IOBase* b, UniXML_iterator& it, SMInterface* shm, const s
b->noprecision = initIntProp(it,"noprecision",prefix,init_prefix_only);
b->value = b->defval;
b->breaklim = initIntProp(it,"breaklim",prefix,init_prefix_only);
b->rawdata = initIntProp(it,"rawdata",prefix,init_prefix_only);
long msec = initIntProp(it,"debouncedelay",prefix,init_prefix_only, UniSetTimer::WaitUpTime);
b->ptDebounce.setTiming(msec);
......
......@@ -197,22 +197,40 @@ TEST_CASE("VTypes: F4","[vtypes][F4]")
}
SECTION("'float' constructor")
{
F4 v( numeric_limits<float>::max() );
REQUIRE( (float)v == numeric_limits<float>::max() );
{
F4 v( numeric_limits<float>::max() );
REQUIRE( (float)v == numeric_limits<float>::max() );
}
{
F4 v( numeric_limits<float>::min() );
REQUIRE( (float)v == numeric_limits<float>::min() );
}
}
SECTION("Modbus constructor")
{
float f = 2^32;
ModbusRTU::ModbusData data[4];
memcpy(data,&f,sizeof(data));
F4 v1(data,4);
REQUIRE( (float)v1 == f );
ModbusRTU::ModbusData data5[5];
memset(data5,0,sizeof(data5));
memcpy(data5,&f,4*sizeof(ModbusRTU::ModbusData));
F4 v2(data5,5);
REQUIRE( (float)v2 == f );
{
float f = numeric_limits<float>::max();
ModbusRTU::ModbusData data[4];
memcpy(data,&f,sizeof(data));
F4 v1(data,4);
REQUIRE( (float)v1 == f );
}
{
float f = numeric_limits<float>::max();
ModbusRTU::ModbusData data5[5];
memset(data5,0,sizeof(data5));
memcpy(data5,&f,4*sizeof(ModbusRTU::ModbusData));
F4 v2(data5,5);
REQUIRE( (float)v2 == f );
}
{
float f = numeric_limits<float>::min();
ModbusRTU::ModbusData data[4];
memcpy(data,&f,sizeof(data));
F4 v1(data,4);
REQUIRE( (float)v1 == f );
}
}
}
......
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