Commit ce4ba08d authored by Pavel Vainerman's avatar Pavel Vainerman

add mtr setup utility and API

parent 4b56f990
......@@ -3,7 +3,7 @@
Name: libuniset
Version: 0.97
Release: eter56
Release: eter58
Summary: UniSet - library for building distributed industrial control systems
License: GPL
Group: Development/C++
......@@ -143,7 +143,8 @@ rm -f %buildroot%_libdir/*.la
%_bindir/%oname-iocalibr
%_bindir/%oname-logicproc
%_bindir/%oname-plogicproc
%_bindir/mtrconv
%_bindir/mtr-conv
%_bindir/mtr-setup
%_bindir/vtconv
%_bindir/rtustate
%_bindir/%oname-rtuexchange
......@@ -183,6 +184,15 @@ rm -f %buildroot%_libdir/*.la
%exclude %_pkgconfigdir/libUniSet.pc
%changelog
* Sun Mar 14 2010 Pavel Vainerman <pv@altlinux.ru> 0.97-eter58
- minor fixes in MTR setup API
* Sun Mar 14 2010 Pavel Vainerman <pv@altlinux.ru> 0.97-eter57
- add MTR setup (API and utility)
* Sat Mar 13 2010 Pavel Vainerman <pv@altlinux.ru> 0.97-eter56
- new build
* Fri Mar 12 2010 Pavel Vainerman <pv@altlinux.ru> 0.97-eter55
- new build
......
bin_PROGRAMS = @PACKAGE@-rtuexchange mtrconv rtustate vtconv
bin_PROGRAMS = @PACKAGE@-rtuexchange mtr-conv rtustate vtconv mtr-setup
lib_LTLIBRARIES = libUniSetRTU.la
libUniSetRTU_la_LIBADD = $(top_builddir)/lib/libUniSet.la \
......@@ -15,9 +15,13 @@ libUniSetRTU_la_SOURCES = RTUStorage.cc RTUExchange.cc
$(SIGC_LIBS)
@PACKAGE@_rtuexchange_CXXFLAGS = -I$(top_builddir)/extensions/include -I$(top_builddir)/extensions/SharedMemory $(SIGC_CFLAGS)
mtrconv_SOURCES = mtrconv.cc
mtrconv_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la
mtrconv_CXXFLAGS = -I$(top_builddir)/extensions/include
mtr_conv_SOURCES = mtrconv.cc
mtr_conv_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la
mtr_conv_CXXFLAGS = -I$(top_builddir)/extensions/include
mtr_setup_SOURCES = mtr-setup.cc
mtr_setup_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la
mtr_setup_CXXFLAGS = -I$(top_builddir)/extensions/include
vtconv_SOURCES = vtconv.cc
vtconv_LDADD = $(top_builddir)/extensions/lib/libUniSetExtensions.la $(top_builddir)/lib/libUniSet.la
......
......@@ -248,7 +248,35 @@ int main( int argc, char **argv )
case cmdSave:
{
return MTR::update_configuration(&mb,slaveaddr,mtrconfile,verb,speed) ? 0 : 1;
if( slaveaddr == 0x00 )
{
if( verb )
cout << "(mtr-setup): save: autodetect slave addr... (speed=" << speed << ")" << endl;
mb.setTimeout(50);
slaveaddr = ModbusHelpers::autodetectSlave(&mb,beg,end,MTR::regModelNumber,ModbusRTU::fnReadInputRegisters);
mb.setTimeout(tout);
}
if( speed.empty() )
{
if( verb )
cout << "(mtr-setup): save: autodetect speed... (addr=" << ModbusRTU::addr2str(slaveaddr) << ")" << endl;
mb.setTimeout(50);
ComPort::Speed s = ModbusHelpers::autodetectSpeed(&mb,slaveaddr,MTR::regModelNumber,ModbusRTU::fnReadInputRegisters);
mb.setSpeed(s);
mb.setTimeout(tout);
}
if( verb )
cout << "(mtr-setup): save: "
<< " slaveaddr=" << ModbusRTU::addr2str(slaveaddr)
<< " confile=" << mtrconfile
<< " speed=" << speed
<< endl;
return MTR::update_configuration(&mb,slaveaddr,mtrconfile,verb) ? 0 : 1;
}
break;
......
......@@ -5,9 +5,12 @@
#define _MTR_H_
// -----------------------------------------------------------------------------
#include <string>
#include <map>
#include <list>
#include <cstring>
#include <cmath>
#include "modbus/ModbusTypes.h"
#include "ComPort.h"
// -----------------------------------------------------------------------------
class ModbusRTUMaster;
// -----------------------------------------------------------------------------
......@@ -79,7 +82,25 @@ namespace MTR
bool setStopBit( ModbusRTUMaster* mb, ModbusRTU::ModbusAddr addr, bool state );
bool setParity( ModbusRTUMaster* mb, ModbusRTU::ModbusAddr addr, mtrParity p );
bool setDataBits( ModbusRTUMaster* mb, ModbusRTU::ModbusAddr addr, mtrDataBits d );
ComPort::Parity get_parity( ModbusRTU::ModbusData data );
ComPort::Speed get_speed( ModbusRTU::ModbusData data );
// -------------------------------------------------------------------------
// .
bool update_configuration( ModbusRTUMaster* mb, ModbusRTU::ModbusAddr addr,
const std::string mtrconfile, int verbose=0 );
// ---------------------------
//
typedef std::list<ModbusRTU::ModbusData> DataList;
typedef std::map<ModbusRTU::ModbusData,DataList> DataMap;
static int attempts = 3; //
static const ModbusRTU::ModbusData skip[] = {48, 49, 59}; // registers which should not write
bool send_param( ModbusRTUMaster* mb, DataMap& dmap, ModbusRTU::ModbusAddr addr, int verb );
bool read_param( const std::string str, std::string& str1, std::string& str2 );
DataMap read_confile( const std::string f );
void update_communication_params( ModbusRTU::ModbusAddr reg, ModbusRTU::ModbusData data,
ModbusRTUMaster* mb, ModbusRTU::ModbusAddr& addr, int verb );
// -------------------------------------------------------------------------
static const int u2size = 2;
// -------------------------------------------------------------------------
......
......@@ -2,7 +2,10 @@
//! \version $Id: MTR.cc,v 1.1 2008/12/14 21:57:50 vpashka Exp $
// --------------------------------------------------------------------------
#include <cmath>
#include <vector>
#include <algorithm>
#include "modbus/ModbusRTUMaster.h"
#include "modbus/ModbusHelpers.h"
#include "MTR.h"
// --------------------------------------------------------------------------
using namespace std;
......@@ -207,5 +210,236 @@ std::string getSerialNumber( ModbusRTUMaster* mb, ModbusRTU::ModbusAddr addr )
return "";
}
// -----------------------------------------------------------------------------
DataMap read_confile( const std::string f )
{
bool start = false;
DataMap dmap;
std::ifstream ifs(f.c_str(),std::ios::in);
if( ifs )
{
while( !ifs.eof() )
{
std::string str;
if( getline(ifs,str) )
{
if( str.empty() )
continue;
if( !start )
{
str = str.substr(0,str.size()-1); // remove \n\r
// cout << "check str: " << str << endl;
if( str == "[Settings]" )
{
start = true;
continue;
}
else
continue;
}
string s_reg, s_data;
if( read_param(str,s_reg,s_data) )
{
ModbusRTU::ModbusData reg = ModbusRTU::str2mbData(s_reg);
/* we can write only registers > 40000 (see MTR-2 manual) */
if( reg <= 40000 )
continue;
reg -= 40000;
// cout << "reg=" << s_reg
// << " data=" << s_data << endl;
DataList dlst;
int k=0;
std::vector<unsigned char> v(4);
for( int i=0; i<s_data.size(); i++ )
{
v[k++] = s_data[i];
if( k>3 )
{
k=0;
string tmp(v.begin(),v.end());
tmp = "0x" + tmp;
// cout << "find data=" << ModbusRTU::str2mbData(tmp)
// << "(" << tmp << ")" << endl;
dlst.push_back( ModbusRTU::str2mbData(tmp) );
}
}
dmap[reg] = dlst;
}
}
}
}
ifs.close();
return dmap;
}
// --------------------------------------------------------------------------
bool read_param( const std::string str, std::string& str1, std::string& str2 )
{
string::size_type pos = str.find('=');
if( pos==string::npos )
return false;
str1 = str.substr(0,pos);
str2 = str.substr(pos+1,str.size());
return true;
}
// ------------------------------------------------------------------------------------------
ComPort::Speed get_speed( ModbusRTU::ModbusData data )
{
static const ComPort::Speed speed_conv[] = { ComPort::ComSpeed1200,
ComPort::ComSpeed2400, ComPort::ComSpeed4800, ComPort::ComSpeed9600,
ComPort::ComSpeed19200, ComPort::ComSpeed38400, ComPort::ComSpeed57600,
ComPort::ComSpeed115200 };
if( data >= sizeof(speed_conv)/sizeof(speed_conv[0]) )
return ComPort::ComSpeed0;
return speed_conv[data];
}
// ------------------------------------------------------------------------------------------
ComPort::Parity get_parity( ModbusRTU::ModbusData data )
{
static const ComPort::Parity parity_conv[] = {
ComPort::NoParity, ComPort::Odd, ComPort::Even };
if( data >= sizeof(parity_conv)/sizeof(parity_conv[0]) )
return ComPort::NoParity;
return parity_conv[data];
}
// ------------------------------------------------------------------------------------------
void update_communication_params( ModbusRTU::ModbusAddr reg, ModbusRTU::ModbusData data,
ModbusRTUMaster* mb, ModbusRTU::ModbusAddr& addr, int verb )
{
if( reg == 55 )
{
addr = data;
if( verb )
cout << "(mtr-setup): slaveaddr is set to "
<< ModbusRTU::addr2str(addr) << endl;
}
else if( reg == 56 )
{
ComPort::Speed speed = get_speed(data);
if( speed != ComPort::ComSpeed0 )
{
mb->setSpeed(speed);
if( verb )
cout << "(mtr-setup): speed is set to "
<< ComPort::getSpeed(speed) << endl;
}
}
else if( reg == 57 )
{
if( data == 0 )
mb->setStopBits(ComPort::OneBit);
else if( data == 1)
mb->setStopBits(ComPort::TwoBits);
else return;
if( verb )
cout << "(mtr-setup): number of stop bits is set to "
<< data + 1 << endl;
}
else if( reg == 58 )
{
if (data != 0 && data != 1 && data != 2)
return;
mb->setParity(get_parity(data));
if( verb )
cout << "(mtr-setup): parity is set to "
<< (data ? ((data == 1) ? "odd" : "even") : "no") << endl;
}
}
// ------------------------------------------------------------------------------------------
bool send_param( ModbusRTUMaster* mb, DataMap& dmap, ModbusRTU::ModbusAddr addr, int verb )
{
if( !mb )
{
cerr << "(MTR::send_param): mb=NULL!" << endl;
return false;
}
for( DataMap::iterator it=dmap.begin(); it!=dmap.end(); ++it )
{
// ModbusRTU::WriteOutputMessage msg(addr,it->first);
// cout << "send reg=" << ModbusRTU::dat2str(it->first)
// << "(" << it->first << ")" << endl;
int reg = it->first;
bool ok = false;
for( DataList::iterator it1=it->second.begin(); it1!=it->second.end(); ++it1, reg++ )
{
const ModbusRTU::ModbusData *last = skip + sizeof(skip)/sizeof(skip[0]);
if( std::find(skip, last, reg) != last)
continue;
cout << "send reg=" << ModbusRTU::dat2str(reg)
<< "(" << reg << ")"
<< "=" << ModbusRTU::dat2str( (*it1) ) << endl;
// ok=true;
// continue;
for( int i=0; i<attempts; i++ )
{
try
{
ModbusRTU::WriteSingleOutputRetMessage ret = mb->write06(addr,reg,(*it1));
if( verb )
cout << "(mtr-setup): write reply: " << ret << endl;
update_communication_params(reg, *it1, mb, addr, verb);
ok = true;
break;
}
catch( ModbusRTU::mbException& ex )
{
/* if speed is changed we receive a timeout error */
if( reg == 56 && it->first == ModbusRTU::erTimeOut )
{
update_communication_params(reg, *it1, mb, addr, verb);
ok = true;
break;
}
else
{
cerr << "(mtr-setup): error for write reg="
<< ModbusRTU::dat2str(reg)
<< "(" << it->first << "): " << ex << endl;
}
}
}
}
// if( !ok )
// return false;
}
return true;
}
// ------------------------------------------------------------------------------------------
bool update_configuration( ModbusRTUMaster* mb, ModbusRTU::ModbusAddr slaveaddr,
const std::string mtrconfile, int verb )
{
std::string m = MTR::getModelNumber(mb, slaveaddr);
if( m != "MTR315Transducer" )
{
cerr << "(mtr-setup): model number != 'MTR315Transducer' (read: " << m << ")" << endl;
return false;
}
DataMap dmap = MTR::read_confile(mtrconfile);
if( dmap.empty() )
{
cerr << "(mtr-setup): error read confile=" << mtrconfile << endl;
return false;
}
if( send_param(mb,dmap,slaveaddr,verb) )
return true;
return false;
}
// ------------------------------------------------------------------------------------------
} // end of namespace MTR
// -----------------------------------------------------------------------------
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