Commit ded0405d authored by Pavel Vainerman's avatar Pavel Vainerman

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

(Modbus): реализовал возможность для MBSlave задавать в конфигурационном файле (xml) карту ответов на запрос 0x2B/0x0E (MEI).
parent fb2c35d3
......@@ -14,6 +14,8 @@ static struct option longopts[] = {
{ "read02", required_argument, 0, 'b' },
{ "read03", required_argument, 0, 'r' },
{ "read04", required_argument, 0, 'x' },
// { "read4313", required_argument, 0, 'u' },
{ "read4314", required_argument, 0, 'e' },
{ "write05", required_argument, 0, 'f' },
{ "write06", required_argument, 0, 'z' },
{ "write0F", required_argument, 0, 'm' },
......@@ -41,6 +43,8 @@ static void print_help()
printf("[--read03] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n");
printf("[--read04] slaveaddr reg count - read from reg (from slaveaddr). Default: count=1\n");
printf("[--diag08] slaveaddr subfunc [dat] - diagnostics request\n");
printf("[--read4314] slaveaddr devID objID - (0x2B/0x0E): read device identification (devID=[1...4], objID=[0..255])\n");
// printf("[--read43-13] slaveaddr ... - (0x2B/0x0D): CANopen General Reference Request and Response PDU \n");
printf("[-i|--iaddr] ip - Modbus server ip. Default: 127.0.0.1\n");
printf("[-a|--myaddr] addr - Modbus address for master. Default: 0x01.\n");
printf("[-p|--port] port - Modbus server port. Default: 502.\n");
......@@ -57,6 +61,8 @@ enum Command
cmdRead02,
cmdRead03,
cmdRead04,
cmdRead43_13,
cmdRead43_14,
cmdWrite05,
cmdWrite06,
cmdWrite0F,
......@@ -86,10 +92,12 @@ int main( int argc, char **argv )
int tout = 2000;
DebugStream dlog;
int ncycles = -1;
ModbusRTU::ModbusByte devID = 0;
ModbusRTU::ModbusByte objID = 0;
try
{
while( (opt = getopt_long(argc, argv, "hva:w:z:r:x:c:b:d:s:t:p:i:ol:d:",longopts,&optindex)) != -1 )
while( (opt = getopt_long(argc, argv, "hva:w:z:r:x:c:b:d:s:t:p:i:ol:d:e:u:",longopts,&optindex)) != -1 )
{
switch (opt)
{
......@@ -107,7 +115,7 @@ int main( int argc, char **argv )
if( cmd == cmdNOP )
cmd = cmdRead03;
case 'x':
{
if( cmd == cmdNOP )
cmd = cmdRead04;
slaveaddr = ModbusRTU::str2mbAddr( optarg );
......@@ -122,6 +130,28 @@ int main( int argc, char **argv )
if( checkArg(optind+1,argc,argv) )
count = uni_atoi(argv[optind+1]);
}
break;
case 'e':
{
if( cmd == cmdNOP )
cmd = cmdRead43_14;
slaveaddr = ModbusRTU::str2mbAddr( optarg );
if( optind > argc )
{
cerr << "read command error: bad or no arguments..." << endl;
return 1;
}
if( checkArg(optind,argc,argv) )
devID = ModbusRTU::str2mbData(argv[optind]);
if( checkArg(optind+1,argc,argv) )
objID = uni_atoi(argv[optind+1]);
}
break;
case 'f':
......@@ -354,6 +384,24 @@ int main( int argc, char **argv )
}
break;
case cmdRead43_14:
{
if( verb )
{
cout << "read4314: slaveaddr=" << ModbusRTU::addr2str(slaveaddr)
<< " devID=" << ModbusRTU::dat2str(devID)
<< " objID=" << ModbusRTU::dat2str(objID)
<< endl;
}
ModbusRTU::MEIMessageRetRDI ret = mb.read4314(slaveaddr,devID,objID);
if( verb )
cout << "(reply): " << ret << endl;
else
cout << "(reply): devID='" << (int)ret.devID << "' objNum='" << (int)ret.objNum << "'" << endl << ret.dlist << endl;
}
break;
case cmdWrite05:
{
if( verb )
......
......@@ -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) );
......@@ -240,6 +241,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()
......@@ -1460,3 +1560,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;
}
// -------------------------------------------------------------------------
......@@ -53,7 +53,6 @@ class MBSlave:
IOProperty():
mbreg(0),
amode(amRW),
vtype(VTypes::vtUnknown),
wnum(0)
{}
......@@ -185,6 +184,7 @@ class MBSlave:
bool respond_invert;
PassiveTimer ptTimeout;
ModbusRTU::mbErrCode prev;
long askCount;
typedef std::map<ModbusRTU::mbErrCode,unsigned int> ExchangeErrorMap;
ExchangeErrorMap errmap; /*!< статистика обмена */
......
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