Commit eb617a40 authored by Pavel Vainerman's avatar Pavel Vainerman

(ModbusMaster): рефакторинг функции оптимизации запросов

(разбил на несколько маленьких), и небольшие правки (const, названия)
parent c6d644a4
......@@ -597,21 +597,21 @@ namespace uniset
for( const auto& m : d.pollmap )
{
for( const auto& it : * (m.second) )
for( const auto& it : *(m.second) )
os << " " << it.second << endl;
}
return os;
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBExchange::RegInfo* r )
std::ostream& operator<<( std::ostream& os, const MBExchange::RegInfo* r )
{
return os << (*r);
}
// -----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, MBExchange::RegInfo& r )
std::ostream& operator<<( std::ostream& os, const MBExchange::RegInfo& r )
{
os << " id=" << r.id
os << " id=" << r.regID
<< " mbreg=" << ModbusRTU::dat2str(r.mbreg)
<< " mbfunc=" << r.mbfunc
<< " q_num=" << r.q_num
......@@ -620,84 +620,95 @@ namespace uniset
<< " mtrType=" << MTR::type2str(r.mtrType)
<< endl;
for( auto it = r.slst.begin(); it != r.slst.end(); ++it )
os << " " << (*it) << endl;
for( const auto& s: r.slst )
os << " " << s << endl;
return os;
}
// -----------------------------------------------------------------------------
void MBExchange::rtuQueryOptimization( RTUDeviceMap& dm )
{
if( noQueryOptimization )
return;
mbinfo << myname << "(rtuQueryOptimization): optimization..." << endl;
for( const auto& d: dm )
rtuQueryOptimizationForDevice(d.second);
for( auto && it1 : dm )
// printMap(dm);
// assert(false);
}
// -----------------------------------------------------------------------------
void MBExchange::rtuQueryOptimizationForDevice( const std::shared_ptr<RTUDevice>& d )
{
auto d = it1.second;
mbinfo << myname << "(rtuQueryOptimizationForDevice): dev addr="
<< ModbusRTU::addr2str(d->mbaddr) << " optimization..." << endl;
for( auto && m : d->pollmap )
for( const auto& m : d->pollmap )
rtuQueryOptimizationForRegMap(m.second);
}
// -----------------------------------------------------------------------------
void MBExchange::rtuQueryOptimizationForRegMap( const std::shared_ptr<RegMap>& regmap )
{
auto& regmap = m.second;
if( regmap->size() <= 1 )
return;
// Вообще в map они уже лежат в нужном порядке, т.е. функция genRegID() гарантирует
// что регистры идущие подряд с одниковой функцией чтения/записи получат подряд идущие ID.
// так что оптимтизация это просто нахождение мест где id идут не подряд...
// что регистры идущие подряд с одниковой функцией чтения/записи получат подряд идущие RegID.
// так что оптимтизация это просто нахождение мест где RegID идут не подряд...
for( auto it = regmap->begin(); it != regmap->end(); ++it )
{
auto beg = it;
ModbusRTU::RegID id = it->second->id; // или собственно it->first
beg->second->q_num = 1;
beg->second->q_count = 1;
auto& beg = it->second;
ModbusRTU::RegID regID = beg->regID;
beg->q_count = 1;
beg->q_num = 0;
++it;
// склеиваем регистры идущие подряд
for( ; it != regmap->end(); ++it )
{
if( (it->second->id - id) > 1 )
if( (it->second->regID - regID) > 1 )
{
--it; // раз это регистр уже следующий, то надо вернуть на шаг обратно..
// этот регистр должен войти уже в следующий запрос,
// надо вернуть на шаг обратно..
--it;
break;
}
beg->second->q_count++;
beg->q_count++;
regID = it->second->regID;
it->second->q_num = beg->q_count-1;
it->second->q_count = 0;
if( beg->second->q_count >= maxQueryCount )
if( beg->q_count >= maxQueryCount )
break;
id = it->second->id;
it->second->q_num = beg->second->q_count;
it->second->q_count = 0;
}
// check correct function...
if( beg->second->q_count > 1 && beg->second->mbfunc == ModbusRTU::fnWriteOutputSingleRegister )
// Корректировка типа функции, в случае необходимости...
if( beg->q_count > 1 && beg->mbfunc == ModbusRTU::fnWriteOutputSingleRegister )
{
mbwarn << myname << "(rtuQueryOptimization): "
<< " optimization change func=" << ModbusRTU::fnWriteOutputSingleRegister
<< " <--> func=" << ModbusRTU::fnWriteOutputRegisters
<< " for mbaddr=" << ModbusRTU::addr2str(d->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(beg->second->mbreg);
<< " for mbaddr=" << ModbusRTU::addr2str(beg->dev->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(beg->mbreg);
beg->second->mbfunc = ModbusRTU::fnWriteOutputRegisters;
beg->mbfunc = ModbusRTU::fnWriteOutputRegisters;
}
else if( beg->second->q_count > 1 && beg->second->mbfunc == ModbusRTU::fnForceSingleCoil )
else if( beg->q_count > 1 && beg->mbfunc == ModbusRTU::fnForceSingleCoil )
{
mbwarn << myname << "(rtuQueryOptimization): "
<< " optimization change func=" << ModbusRTU::fnForceSingleCoil
<< " <--> func=" << ModbusRTU::fnForceMultipleCoils
<< " for mbaddr=" << ModbusRTU::addr2str(d->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(beg->second->mbreg);
<< " for mbaddr=" << ModbusRTU::addr2str(beg->dev->mbaddr)
<< " mbreg=" << ModbusRTU::dat2str(beg->mbreg);
beg->second->mbfunc = ModbusRTU::fnForceMultipleCoils;
beg->mbfunc = ModbusRTU::fnForceMultipleCoils;
}
// надо до внешнего цикла, где будет ++it
// проверить условие.. (т.к. мы во внутреннем цикле итерировались
if( it == regmap->end() )
break;
}
}
}
}
// -----------------------------------------------------------------------------
//std::ostream& operator<<( std::ostream& os, MBExchange::PList& lst )
std::ostream& MBExchange::print_plist( std::ostream& os, const MBExchange::PList& lst )
......@@ -706,8 +717,8 @@ namespace uniset
os << "[ ";
for( auto it = lst.begin(); it != lst.end(); ++it )
os << "(" << it->si.id << ")" << conf->oind->getBaseName(conf->oind->getMapName(it->si.id)) << " ";
for( const auto& p: lst )
os << "(" << p.si.id << ")" << conf->oind->getBaseName(conf->oind->getMapName(p.si.id)) << " ";
os << "]";
......@@ -2231,10 +2242,10 @@ namespace uniset
return d;
}
// ------------------------------------------------------------------------------------------
std::shared_ptr<MBExchange::RegInfo> MBExchange::addReg( std::shared_ptr<RegMap>& mp, ModbusRTU::RegID id, ModbusRTU::ModbusData r,
std::shared_ptr<MBExchange::RegInfo> MBExchange::addReg( std::shared_ptr<RegMap>& mp, ModbusRTU::RegID regID, ModbusRTU::ModbusData r,
UniXML::iterator& xmlit, std::shared_ptr<MBExchange::RTUDevice> dev )
{
auto it = mp->find(id);
auto it = mp->find(regID);
if( it != mp->end() )
{
......@@ -2253,7 +2264,7 @@ namespace uniset
}
mbinfo << myname << "(addReg): reg=" << ModbusRTU::dat2str(r)
<< "(id=" << id << ")"
<< "(id=" << regID << ")"
<< " already added for " << (*it->second)
<< " Ignore register params for " << xmlit.getProp("name") << " ..." << endl;
......@@ -2267,12 +2278,12 @@ namespace uniset
return 0;
ri->mbreg = r;
ri->id = id;
ri->regID = regID;
mp->insert( std::make_pair(id, ri) );
ri->rit = mp->find(id);
mp->insert( std::make_pair(regID, ri) );
ri->rit = mp->find(regID);
mbinfo << myname << "(addReg): reg=" << ModbusRTU::dat2str(r) << "(id=" << id << ")" << endl;
mbinfo << myname << "(addReg): reg=" << ModbusRTU::dat2str(r) << "(id=" << regID << ")" << endl;
return ri;
}
......
......@@ -145,7 +145,7 @@ namespace uniset
ModbusRTU::ModbusData mbreg = { 0 }; /*!< регистр */
ModbusRTU::SlaveFunctionCode mbfunc = { ModbusRTU::fnUnknown }; /*!< функция для чтения/записи */
PList slst;
ModbusRTU::RegID id = { 0 };
ModbusRTU::RegID regID = { 0 };
std::shared_ptr<RTUDevice> dev;
......@@ -158,7 +158,7 @@ namespace uniset
// optimization
size_t q_num = { 0 }; /*!< number in query */
size_t q_count = { 0 }; /*!< count registers for query */
size_t q_count = { 1 }; /*!< count registers for query */
RegMap::iterator rit;
......@@ -174,8 +174,8 @@ namespace uniset
bool sm_initOK = { false }; /*!< инициализировалось ли значение из SM */
};
friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
friend std::ostream& operator<<( std::ostream& os, RegInfo* r );
friend std::ostream& operator<<( std::ostream& os, const RegInfo& r );
friend std::ostream& operator<<( std::ostream& os, const RegInfo* r );
struct RTUDevice
{
......@@ -288,6 +288,9 @@ namespace uniset
bool pollRTU( std::shared_ptr<RTUDevice>& dev, RegMap::iterator& it );
void updateSM();
// в функции передаётся итератор,
// т.к. в них идёт итерирование в случае если запрос в несколько регистров
void updateRTU(RegMap::iterator& it);
void updateMTR(RegMap::iterator& it);
void updateRTU188(RegMap::iterator& it);
......@@ -322,6 +325,8 @@ namespace uniset
std::string initPropPrefix( const std::string& def_prop_prefix = "" );
void rtuQueryOptimization( RTUDeviceMap& m );
void rtuQueryOptimizationForDevice( const std::shared_ptr<RTUDevice>& d );
void rtuQueryOptimizationForRegMap( const std::shared_ptr<RegMap>& regmap );
xmlNode* cnode = { 0 };
std::string s_field;
......
......@@ -64,6 +64,7 @@ MBTCPMaster::MBTCPMaster(uniset::ObjectId objId, uniset::ObjectId shmId,
if( shm->isLocalwork() )
{
readConfiguration();
if( !noQueryOptimization )
rtuQueryOptimization(devices);
initDeviceList();
}
......
......@@ -181,6 +181,7 @@ MBTCPMultiMaster::MBTCPMultiMaster( uniset::ObjectId objId, uniset::ObjectId shm
if( shm->isLocalwork() )
{
readConfiguration();
if( !noQueryOptimization )
rtuQueryOptimization(devices);
initDeviceList();
}
......
......@@ -85,6 +85,7 @@ RTUExchange::RTUExchange(uniset::ObjectId objId, uniset::ObjectId shmId, const s
if( shm->isLocalwork() )
{
readConfiguration();
if( !noQueryOptimization )
rtuQueryOptimization(devices);
initDeviceList();
}
......
......@@ -123,6 +123,14 @@
<item id="1053" safeval="42" mb="1" mbtype="rtu" mbaddr="0x02" mbreg="10" mbfunc="0x03" iotype="AI" name="SafeMode2_TestRead03" textname="(safemode): Тестовый регистр для 0x03"/>
<item id="1054" safeval="1" mb="1" mbtype="rtu" mbaddr="0x02" mbreg="11" mbfunc="0x02" iotype="DI" name="SafeMode2_TestRead02" textname="(safemode): Тестовый регистр для 0x02"/>
<!-- query optimization test -->
<item id="1060" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="200" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization1_F2" textname="F2: Тестовый регистр для 0x03"/>
<item id="1061" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="202" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization2_F2" textname="F2: Тестовый регистр для 0x03"/>
<item id="1062" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="204" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization3_F2" textname="F2: Тестовый регистр для 0x03"/>
<item id="1063" mb="1" mbtype="rtu" mbaddr="0x01" mbreg="206" mbfunc="0x03" vtype="F2" iotype="AI" name="TestQueryOptimization4_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="10000" iotype="DI" name="TestMode_S" textname="Тестовый датчик"/>
</sensors>
......
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