Commit 91f2a789 authored by Pavel Vainerman's avatar Pavel Vainerman

(Modbus): реализовал возможность для MBSlave задавать в конфигурационном файле…

(Modbus): реализовал возможность для MBSlave задавать в конфигурационном файле (xml) карту ответов на запрос 0x2B/0x0E (MEI).
parent 53a7a495
......@@ -397,8 +397,8 @@ int main( int argc, char **argv )
ModbusRTU::MEIMessageRetRDI ret = mb.read4314(slaveaddr,devID,objID);
if( verb )
cout << "(reply): " << ret << endl;
else
cout << "(reply): objNum=" << (int)ret.objNum << endl << ret.dlist << endl;
else
cout << "(reply): devID='" << (int)ret.devID << "' objNum='" << (int)ret.objNum << "'" << endl << ret.dlist << endl;
}
break;
......
......@@ -2,7 +2,7 @@
ulimit -Sc 1000000
uniset-start.sh -f ./uniset-nullController --name SharedMemory --confile test.xml --unideb-add-levels info,crit,warn,level9,system
uniset-start.sh -f ./uniset-nullController --name SharedMemory1 --confile test.xml --unideb-add-levels info,crit,warn,level9,system
#info,warn,crit,system,level9 > 1.log
#--c-filter-field cfilter --c-filter-value test1 --s-filter-field io --s-filter-value 1
......@@ -63,6 +63,43 @@
<item directory="/tmp/" id="3" name="configure.xml.gz"/>
<item directory="ConfDir" id="4" name="SERIAL"/>
</filelist>
<MEI>
<!-- ВНИМАНИЕ: должен заполняться в соответсвии со стандартом. ObjectID и DeviceID не случайны.. -->
<device id="0x01">
<object id="0" comm="VendorName">
<string value="etersoft"/>
</object>
<object id="1" comm="ProductCode">
<string value="uniset"/>
</object>
<object id="2" comm="MajorMinorRevision">
<string value="1.6"/>
</object>
</device>
<device id="0x02">
<object id="3" comm="VendorURL">
<string value="http://www.etersoft.ru"/>
</object>
<object id="4" comm="ProductName">
<string value="uniset"/>
</object>
<object id="5" comm="ModelName">
<string value="uniset:MBSlave"/>
</object>
<object id="6" comm="UserApplicationName">
<string value="MBSlave1"/>
</object>
</device>
<device id="0x03">
<object id="128" comm="private objects">
<string id="129" value="etersoft"/>
<string id="130" value="uniset"/>
<string id="131" value="1.6"/>
<string id="132" value="http://www.etersoft.ru"/>
<string id="133" value="MBSlave1"/>
</object>
</device>
</MEI>
</MBSlave1>
<RTUExchange name="RTUExchange" speed="38400">
<DeviceList>
......@@ -152,9 +189,9 @@
</sensor>
</thresholds>
<controllers name="Controllers">
<item name="SharedMemory"/>
<item name="UniExchange"/>
<item name="UniExchange2"/>
<item id="5000" name="SharedMemory1"/>
<item id="5001" name="UniExchange"/>
<item id="5002" name="UniExchange2"/>
</controllers>
<!-- ******************* Идентификаторы сервисов ***************** -->
<services name="Services">
......
......@@ -121,6 +121,7 @@ prefix(prefix)
mbslot->connectForceCoils( sigc::mem_fun(this, &MBSlave::forceMultipleCoils) );
mbslot->connectWriteOutput( sigc::mem_fun(this, &MBSlave::writeOutputRegisters) );
mbslot->connectWriteSingleOutput( sigc::mem_fun(this, &MBSlave::writeOutputSingleRegister) );
mbslot->connectMEIRDI( sigc::mem_fun(this, &MBSlave::read4314) );
if( findArgParam("--" + prefix + "-allow-setdatetime",conf->getArgc(),conf->getArgv())!=-1 )
mbslot->connectSetDateTime( sigc::mem_fun(this, &MBSlave::setDateTime) );
......@@ -244,6 +245,105 @@ prefix(prefix)
else
dlog[Debug::INFO] << myname << "(init): <filelist> not found..." << endl;
// Формирование "карты" ответов на запрос 0x2B(43)/0x0E(14)
xmlNode* mnode = 0;
if( xml )
mnode = xml->extFindNode(cnode,1,1,"MEI");
if( mnode )
{
// Считывается структура для формирования ответов на запрос 0x2B(43)/0x0E(14)
// <MEI>
// <device id="">
// <objects id="">
// <string id="" value=""/>
// <string id="" value=""/>
// <string id="" value=""/>
// ...
// </objects>
// </device>
// <device devID="">
// ...
// </device>
// </MEI>
UniXML_iterator dit(mnode);
if( dit.goChildren() )
{
// Device ID list..
for( ;dit.getCurrent(); dit.goNext() )
{
if( dit.getProp("id").empty() )
{
dlog[Debug::WARN] << myname << "(init): read <MEI>. Unknown <device id=''>. Ignore.." << endl;
continue;
}
int devID = dit.getIntProp("id");
UniXML_iterator oit(dit);
if( oit.goChildren() )
{
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(init): MEI: read dev='" << devID << "'" << endl;
MEIObjIDMap meiomap;
// Object ID list..
for( ;oit.getCurrent(); oit.goNext() )
{
if( dit.getProp("id").empty() )
{
dlog[Debug::WARN] << myname
<< "(init): read <MEI>. Unknown <object id='' (for device id='"
<< devID << "'). Ignore.."
<< endl;
continue;
}
int objID = oit.getIntProp("id");
UniXML_iterator sit(oit);
if( sit.goChildren() )
{
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(init): MEI: read obj='" << objID << "'" << endl;
MEIValMap meivmap;
// request (string) list..
for( ;sit.getCurrent(); sit.goNext() )
{
int vid = objID;
if( sit.getProp("id").empty() )
{
if( dlog.debugging(Debug::WARN) )
dlog[Debug::INFO] << myname << "(init): MEI: dev='" << devID
<< "' obj='" << objID << "'"
<< ". Unknown id='' for value='" << sit.getProp("value") << "'"
<< ". Set objID='" << objID << "'"
<< endl;
}
else
vid = sit.getIntProp("id");
meivmap[vid] = sit.getProp("value");
}
if( !meivmap.empty() )
meiomap[objID] = meivmap;
}
}
if( !meiomap.empty() )
meidev[devID] = meiomap;
}
}
}
if( !meidev.empty() && dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << myname << "(init): <MEI> init ok." << endl;
}
else
dlog[Debug::INFO] << myname << "(init): <MEI> empty..." << endl;
}
// -----------------------------------------------------------------------------
MBSlave::~MBSlave()
......@@ -1467,3 +1567,28 @@ ModbusRTU::mbErrCode MBSlave::diagnostics( ModbusRTU::DiagnosticMessage& query,
return ModbusRTU::erOperationFailed;
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode MBSlave::read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply )
{
if( dlog.debugging(Debug::INFO) )
dlog[Debug::INFO] << "(read4314): " << query << endl;
// if( query.devID <= rdevMinNum || query.devID >= rdevMaxNum )
// return erOperationFailed;
MEIDevIDMap::iterator dit = meidev.find(query.devID);
if( dit == meidev.end() )
return ModbusRTU::erBadDataAddress;
MEIObjIDMap::iterator oit = dit->second.find(query.objID);
if( oit == dit->second.end() )
return ModbusRTU::erBadDataAddress;
reply.mf = 0xFF;
reply.conformity = query.devID;
for( MEIValMap::iterator i=oit->second.begin(); i!=oit->second.end(); i++ )
reply.addData( i->first, i->second );
return erNoError;
}
// -------------------------------------------------------------------------
......@@ -114,6 +114,9 @@ class MBSlave:
ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
ModbusRTU::DiagnosticRetMessage& reply );
ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
ModbusRTU::MEIMessageRetRDI& reply );
/*! Проверка корректности регистра перед сохранением.
Вызывается для каждого регистра не зависимо от используемой функции (06 или 10)
*/
......@@ -199,6 +202,15 @@ class MBSlave:
std::string prefix;
ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET/2+1]; /*!< буфер для формирования ответов */
// данные для ответа на запрос 0x2B(43)/0x0E(14)
// 'MEI' - modbus encapsulated interface
// 'RDI' - read device identification
typedef std::map<int,std::string> MEIValMap;
typedef std::map<int,MEIValMap> MEIObjIDMap;
typedef std::map<int,MEIObjIDMap> MEIDevIDMap;
MEIDevIDMap meidev;
};
// -----------------------------------------------------------------------------
#endif // _MBSlave_H_
......
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