Commit eb617a40 authored by Pavel Vainerman's avatar Pavel Vainerman

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

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