Commit 0ddd3ad8 authored by Pavel Vainerman's avatar Pavel Vainerman

Добавил MVSlaveTest для локальной наладки MBSlave.

parent 9c5730a2
...@@ -407,6 +407,7 @@ AC_CONFIG_FILES([Makefile ...@@ -407,6 +407,7 @@ AC_CONFIG_FILES([Makefile
extensions/MQTTPublisher/libUniSet2MQTTPublisher.pc extensions/MQTTPublisher/libUniSet2MQTTPublisher.pc
extensions/tests/Makefile extensions/tests/Makefile
extensions/tests/SMemoryTest/Makefile extensions/tests/SMemoryTest/Makefile
extensions/tests/MBSlaveTest/Makefile
testsuite/Makefile testsuite/Makefile
python/lib/Makefile python/lib/Makefile
python/lib/pyUniSet/Makefile python/lib/pyUniSet/Makefile
......
...@@ -1903,29 +1903,29 @@ ModbusRTU::mbErrCode MBSlave::real_write_prop( IOProperty* p, ModbusRTU::ModbusD ...@@ -1903,29 +1903,29 @@ ModbusRTU::mbErrCode MBSlave::real_write_prop( IOProperty* p, ModbusRTU::ModbusD
} }
catch( UniSetTypes::NameNotFound& ex ) catch( UniSetTypes::NameNotFound& ex )
{ {
mbwarn << myname << "(write): " << ex << endl; mbwarn << myname << "(real_write_prop): " << ex << endl;
return ModbusRTU::erBadDataAddress; return ModbusRTU::erBadDataAddress;
} }
catch( UniSetTypes::OutOfRange& ex ) catch( UniSetTypes::OutOfRange& ex )
{ {
mbwarn << myname << "(write): " << ex << endl; mbwarn << myname << "(real_write_prop): " << ex << endl;
return ModbusRTU::erBadDataValue; return ModbusRTU::erBadDataValue;
} }
catch( const Exception& ex ) catch( const Exception& ex )
{ {
if( pingOK ) if( pingOK )
mbcrit << myname << "(write): " << ex << endl; mbcrit << myname << "(real_write_prop): " << ex << endl;
} }
catch( const CORBA::SystemException& ex ) catch( const CORBA::SystemException& ex )
{ {
if( pingOK ) if( pingOK )
mbcrit << myname << "(write): СORBA::SystemException: " mbcrit << myname << "(real_write_prop): СORBA::SystemException: "
<< ex.NP_minorString() << endl; << ex.NP_minorString() << endl;
} }
catch(...) catch(...)
{ {
if( pingOK ) if( pingOK )
mbcrit << myname << "(write) catch ..." << endl; mbcrit << myname << "(real_write_prop) catch ..." << endl;
} }
pingOK = false; pingOK = false;
......
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// -------------------------------------------------------------------------
#include <cmath>
#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "MBTCPPersistentSlave.h"
#include "modbus/ModbusRTUSlaveSlot.h"
#include "modbus/ModbusTCPServerSlot.h"
#include "modbus/MBLogSugar.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
using namespace ModbusRTU;
// -----------------------------------------------------------------------------
MBTCPPersistentSlave::MBTCPPersistentSlave(UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmId, const std::shared_ptr<SharedMemory>& ic, const string& prefix ):
MBSlave(objId, shmId, ic, prefix),
sesscount_id(DefaultObjectId)
{
auto conf = uniset_conf();
string conf_name(conf->getArgParam("--" + prefix + "-confnode", myname));
cnode = conf->getNode(conf_name);
if( cnode == NULL )
throw UniSetTypes::SystemError("(MBTCPPersistentSlave): Not found conf-node for " + myname );
UniXML::iterator it(cnode);
waitTimeout = conf->getArgInt("--" + prefix + "-wait-timeout", it.getProp("waitTimeout"));
if( waitTimeout == 0 )
waitTimeout = 4000;
ptUpdateInfo.setTiming(waitTimeout);
vmonit(waitTimeout);
sessTimeout = conf->getArgInt("--" + prefix + "-session-timeout", it.getProp("sessTimeout"));
if( sessTimeout == 0 )
sessTimeout = 2000;
vmonit(sessTimeout);
sessMaxNum = conf->getArgInt("--" + prefix + "-session-maxnum", it.getProp("sessMaxNum"));
if( sessMaxNum == 0 )
sessMaxNum = 3;
vmonit(sessMaxNum);
sesscount_id = conf->getSensorID( conf->getArgParam("--" + prefix + "-session-count-id", it.getProp("sesscount")) );
UniXML::iterator cit(it);
if( cit.find("clients") && cit.goChildren() )
{
for( ; cit; cit++ )
{
ClientInfo c;
c.iaddr = cit.getProp("ip");
if( c.iaddr.empty() )
{
ostringstream err;
err << myname << "(init): Unknown ip=''";
mbcrit << err.str() << endl;
throw SystemError(err.str());
}
// resolve (если получиться)
ost::InetAddress ia(c.iaddr.c_str());
c.iaddr = string( ia.getHostname() );
if( !cit.getProp("respond").empty() )
{
c.respond_s = conf->getSensorID(cit.getProp("respond"));
if( c.respond_s == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): Not found sensor ID for " << cit.getProp("respond");
mbcrit << err.str() << endl;
throw SystemError(err.str());
}
}
if( !cit.getProp("askcount").empty() )
{
c.askcount_s = conf->getSensorID(cit.getProp("askcount"));
if( c.askcount_s == DefaultObjectId )
{
ostringstream err;
err << myname << "(init): Not found sensor ID for " << cit.getProp("askcount");
mbcrit << err.str() << endl;
throw SystemError(err.str());
}
}
c.invert = cit.getIntProp("invert");
if( !cit.getProp("timeout").empty() )
{
c.tout = cit.getIntProp("timeout");
c.ptTimeout.setTiming(c.tout);
}
cmap[c.iaddr] = c;
mbinfo << myname << "(init): add client: " << c.iaddr << " respond=" << c.respond_s << " askcount=" << c.askcount_s << endl;
}
}
}
// -----------------------------------------------------------------------------
MBTCPPersistentSlave::~MBTCPPersistentSlave()
{
}
// -----------------------------------------------------------------------------
void MBTCPPersistentSlave::help_print( int argc, const char* const* argv )
{
MBSlave::help_print(argc, argv);
cerr << endl;
cout << "--prefix-wait-timeout msec - Время ожидания очередного соединения и обновление статистики работы. По умолчанию: 4 сек." << endl;
cout << "--prefix-session-timeout msec - Таймаут на закрытие соединения с 'клиентом', если от него нет запросов. По умолчанию: 10 сек." << endl;
cout << "--prefix-session-maxnum num - Маскимальное количество соединений. По умолчанию: 10." << endl;
cout << "--prefix-session-count-id id - Датчик для отслеживания текущего количества соединений." << endl;
}
// -----------------------------------------------------------------------------
std::shared_ptr<MBTCPPersistentSlave> MBTCPPersistentSlave::init_mbslave( int argc, const char* const* argv, UniSetTypes::ObjectId icID,
const std::shared_ptr<SharedMemory>& ic, const string& prefix )
{
auto conf = uniset_conf();
string name = conf->getArgParam("--" + prefix + "-name", "MBSlave1");
if( name.empty() )
{
cerr << "(mbslave): Не задан name'" << endl;
return 0;
}
ObjectId ID = conf->getObjectID(name);
if( ID == UniSetTypes::DefaultObjectId )
{
cerr << "(mbslave): идентификатор '" << name
<< "' не найден в конф. файле!"
<< " в секции " << conf->getObjectsSection() << endl;
return 0;
}
dinfo << "(mbslave): name = " << name << "(" << ID << ")" << endl;
return make_shared<MBTCPPersistentSlave>(ID, icID, ic, prefix);
}
// -----------------------------------------------------------------------------
void MBTCPPersistentSlave::execute_tcp()
{
auto sslot = dynamic_pointer_cast<ModbusTCPServerSlot>(mbslot);
if( !sslot )
{
mbcrit << myname << "(execute_tcp): DYNAMIC CAST ERROR (mbslot --> ModbusTCPServerSlot)" << std::endl;
raise(SIGTERM);
return;
}
for( auto && i : cmap )
i.second.ptTimeout.reset();
sslot->setMaxSessions( sessMaxNum );
mbinfo << myname << "(execute_tcp): thread running.." << endl;
while( !cancelled )
{
try
{
#warning MBTCPPersistentSlave: Из этой функции нет возврата..
sslot->mainLoop( vaddr );
// ========== В текущей реализации КОД НИЖЕ не будет вызван... по крайней мере пока не завершится процесс ====
// если слишком быстро обработали запрос
// то ничего не делаем..
if( !ptUpdateInfo.checkTime() )
continue;
ptUpdateInfo.reset();
// Обновляем информацию по соединениям
sess.clear();
sslot->getSessions(sess);
for( auto && s : sess )
{
auto i = cmap.find( s.iaddr );
if( i != cmap.end() )
{
// если ещё в списке, значит отвечает (т.е. сбрасываем таймер)
if( i->second.tout == 0 )
i->second.ptTimeout.setTiming( waitTimeout );
else
i->second.ptTimeout.reset();
i->second.askCount = s.askCount;
}
}
// а теперь проходим по списку и выставляем датчики..
for( const auto& it : cmap )
{
auto c = it.second;
mblog4 << myname << "(work): " << c.iaddr << " resp=" << (c.invert ? c.ptTimeout.checkTime() : !c.ptTimeout.checkTime())
<< " askcount=" << c.askCount
<< endl;
if( c.respond_s != DefaultObjectId )
{
try
{
bool st = c.invert ? c.ptTimeout.checkTime() : !c.ptTimeout.checkTime();
shm->localSetValue(c.respond_it, c.respond_s, st, getId());
}
catch( const Exception& ex )
{
mbcrit << myname << "(execute_tcp): " << ex << std::endl;
}
}
if( c.askcount_s != DefaultObjectId )
{
try
{
shm->localSetValue(c.askcount_it, c.askcount_s, c.askCount, getId());
}
catch( const Exception& ex )
{
mbcrit << myname << "(execute_tcp): " << ex << std::endl;
}
}
}
#if 0
if( res != ModbusRTU::erTimeOut )
ptTimeout.reset();
// собираем статистику обмена
if( prev != ModbusRTU::erTimeOut )
{
// с проверкой на переполнение
askCount = askCount >= numeric_limits<long>::max() ? 0 : askCount + 1;
if( res != ModbusRTU::erNoError )
errmap[res]++;
}
prev = res;
if( res != ModbusRTU::erNoError && res != ModbusRTU::erTimeOut )
mblog[Debug::WARN] << myname << "(execute_tcp): " << ModbusRTU::mbErr2Str(res) << endl;
#endif
if( !activated )
continue;
if( sidHeartBeat != DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
shm->localSetValue(itHeartBeat, sidHeartBeat, maxHeartBeat, getId());
ptHeartBeat.reset();
}
catch( const Exception& ex )
{
mbcrit << myname << "(execute_tcp): (hb) " << ex << std::endl;
}
}
if( respond_id != DefaultObjectId )
{
bool state = ptTimeout.checkTime() ? false : true;
if( respond_invert )
state ^= true;
try
{
shm->localSetValue(itRespond, respond_id, (state ? 1 : 0), getId());
}
catch( const Exception& ex )
{
mbcrit << myname << "(execute_rtu): (respond) " << ex << std::endl;
}
}
if( askcount_id != DefaultObjectId )
{
try
{
shm->localSetValue(itAskCount, askcount_id, askCount, getId());
}
catch( const Exception& ex )
{
mbcrit << myname << "(execute_rtu): (askCount) " << ex << std::endl;
}
}
if( sesscount_id != DefaultObjectId )
{
try
{
shm->localSetValue(sesscount_it, sesscount_id, sslot->getCountSessions(), getId());
}
catch( const Exception& ex )
{
mbcrit << myname << "(execute_rtu): (sessCount) " << ex << std::endl;
}
}
}
catch( std::exception& ex)
{
mbwarn << myname << "(execute_tcp): " << ex.what() << endl;
}
}
mbinfo << myname << "(execute_tcp): thread stopped.." << endl;
}
// -----------------------------------------------------------------------------
void MBTCPPersistentSlave::initIterators()
{
MBSlave::initIterators();
shm->initIterator(sesscount_it);
for( auto && i : cmap )
i.second.initIterators(shm);
}
// -----------------------------------------------------------------------------
bool MBTCPPersistentSlave::deactivateObject()
{
if( mbslot )
{
auto sslot = dynamic_pointer_cast<ModbusTCPServerSlot>(mbslot);
if( sslot )
sslot->sigterm(SIGTERM);
}
return MBSlave::deactivateObject();
}
// -----------------------------------------------------------------------------
void MBTCPPersistentSlave::sigterm( int signo )
{
if( mbslot )
{
auto sslot = dynamic_pointer_cast<ModbusTCPServerSlot>(mbslot);
if( sslot )
sslot->sigterm(signo);
}
MBSlave::sigterm(signo);
}
// -----------------------------------------------------------------------------
const std::string MBTCPPersistentSlave::ClientInfo::getShortInfo() const
{
ostringstream s;
s << iaddr << " askCount=" << askCount;
return std::move(s.str());
}
// -----------------------------------------------------------------------------
UniSetTypes::SimpleInfo* MBTCPPersistentSlave::getInfo( CORBA::Long userparam )
{
UniSetTypes::SimpleInfo_var i = MBSlave::getInfo(userparam);
ostringstream inf;
inf << i->info << endl;
inf << "Clients: " << endl;
for( const auto& m : cmap )
inf << " " << m.second.getShortInfo() << endl;
inf << endl;
i->info = inf.str().c_str();
return i._retn();
}
// ----------------------------------------------------------------------------
noinst_PROGRAMS = mbslave-test
mbslave_test_LDADD = $(top_builddir)/lib/libUniSet2.la \
$(top_builddir)/extensions/lib/libUniSet2Extensions.la \
$(top_builddir)/extensions/SharedMemory/libUniSet2SharedMemory.la \
$(top_builddir)/extensions/ModbusSlave/libUniSet2MBSlave.la \
$(SIGC_LIBS) $(COMCPP_LIBS)
mbslave_test_CPPFLAGS = -I$(top_builddir)/include \
-I$(top_builddir)/extensions/include \
-I$(top_builddir)/extensions/SharedMemory \
-I$(top_builddir)/extensions/ModbusSlave \
$(SIGC_CFLAGS) $(COMCPP_CFLAGS)
mbslave_test_SOURCES = TestProc_SK.cc TestProc.cc mbslave-test.cc
BUILT_SOURCES=TestProc_SK.cc TestProc_SK.h
TestProc_SK.cc TestProc_SK.h: testproc.src.xml
$(top_builddir)/Utilities/codegen/@PACKAGE@-codegen -l $(top_builddir)/Utilities/codegen --ask -n TestProc --local-include --topdir $(top_builddir)/ --no-main testproc.src.xml
clean-local:
rm -rf *_SK.cc *_SK.h
include $(top_builddir)/include.mk
#include <iomanip>
#include "Exceptions.h"
#include "TestProc.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
// -----------------------------------------------------------------------------
TestProc::TestProc( UniSetTypes::ObjectId id, xmlNode* confnode ):
TestProc_SK( id, confnode ),
state(false)
{
loglevels.push_back(Debug::INFO);
loglevels.push_back(Debug::WARN);
loglevels.push_back(Debug::CRIT);
loglevels.push_back(Debug::LEVEL1);
loglevels.push_back(Debug::LEVEL2);
loglevels.push_back( Debug::type(Debug::LEVEL2 | Debug::INFO) );
loglevels.push_back( Debug::type(Debug::LEVEL2 | Debug::INFO | Debug::WARN | Debug::CRIT) );
lit = loglevels.begin();
out_log_c = (*lit);
vmonit(undef);
mbPort = 2048; // getId();
ost::InetAddress mbIAddr("localhost");
try
{
ost::Thread::setException(ost::Thread::throwException);
mbslave = make_shared<ModbusTCPServerSlot>(mbIAddr, mbPort);
mbslave->connectWriteSingleOutput( sigc::mem_fun(this, &TestProc::writeOutputSingleRegister) );
loga->add( mbslave->log() );
mbslave->log()->level(Debug::ANY);
mbthr = make_shared< ThreadCreator<TestProc> >(this, &TestProc::mbThread);
myinfo << myname << "(init) ModbusSlave " << mbIP << ":" << mbPort << endl;
}
catch( const ost::SockException& e )
{
ostringstream err;
err << myname << "(init) Can`t create socket " << mbIP << ":" << mbPort << " err: " << e.getString() << endl;
mycrit << err.str() << endl;
throw SystemError(err.str());
}
catch( const std::exception& ex )
{
mycrit << myname << "(init): " << ex.what() << endl;
throw ex;
}
}
// -----------------------------------------------------------------------------
TestProc::~TestProc()
{
}
// -----------------------------------------------------------------------------
TestProc::TestProc():
state(false)
{
cerr << ": init failed!!!!!!!!!!!!!!!" << endl;
throw Exception();
}
// -----------------------------------------------------------------------------
void TestProc::step()
{
}
// -----------------------------------------------------------------------------
void TestProc::sysCommand( const UniSetTypes::SystemMessage* sm )
{
TestProc_SK::sysCommand(sm);
if( sm->command == SystemMessage::StartUp || sm->command == SystemMessage::WatchDog )
{
askTimer(tmCheck, checkTime);
askTimer(tmCheckWorking, checkWorkingTime);
askTimer(tmLogControl, checkLogTime);
if( mbthr )
mbthr->start();
// В начальный момент времени блокирующий датчик =0, поэтому d2_check_s должен быть равен depend_off_value (-50).
cerr << myname << "(startup): check init depend: " << ( getValue(d2_check_s) == -50 ? "ok" : "FAIL" ) << endl;
}
}
// -----------------------------------------------------------------------------
void TestProc::sensorInfo( const SensorMessage* sm )
{
/*
mylog2 << myname << "(sensorInfo): id=" << sm->id << " val=" << sm->value
<< " " << timeToString(sm->sm_tv_sec,":")
<< "(" << setw(6) << sm->sm_tv_usec << "): "
<< endl;
*/
if( sm->id == on_s )
{
if( sm->value )
{
cerr << myname << "(sensorInfo): START WORKING.." << endl;
askTimer(tmChange, changeTime);
}
else
{
askTimer(tmChange, 0);
cerr << myname << "(sensorInfo): STOP WORKING.." << endl;
}
}
else if( sm->id == check_undef_s )
{
cerr << myname << "(sensorInfo): CHECK UNDEFINED STATE ==> " << (sm->undefined == undef ? "ok" : "FAIL") << endl;
}
}
// -----------------------------------------------------------------------------
void TestProc::timerInfo( const TimerMessage* tm )
{
if( tm->id == tmChange )
{
state ^= true;
out_lamp_c = ( state ? lmpBLINK : lmpOFF );
mylog2 << myname << ": state=" << state << " lmp=" << out_lamp_c << endl;
askTimer(tmCheckWorking, 0); // test remove timer
askTimer(tmCheckWorking, checkTime); // reset timer
}
else if( tm->id == tmCheckWorking )
cerr << myname << ": WORKING FAIL!" << endl;
else if( tm->id == tmCheck )
{
cerr << endl << endl << "--------" << endl;
test_depend();
test_undefined_state();
test_thresholds();
test_loglevel();
}
else if( tm->id == tmLogControl )
{
cerr << endl;
cerr << "======= TEST LOG PRINT ======" << endl;
cerr << "LOGLEVEL: [" << (int)(*lit) << "] " << (*lit) << endl;
for( auto& it : loglevels )
mylog->debug(it) << myname << ": test log print..." << endl;
cerr << "======= END LOG PRINT ======" << endl;
}
}
// -----------------------------------------------------------------------------
void TestProc::test_depend()
{
cerr << myname << ": Check depend..." << endl;
long test_val = 100;
// set depend 0...
setValue(depend_c, 0);
setValue(set_d1_check_s, test_val);
setValue(set_d2_check_s, test_val);
cerr << myname << ": check depend OFF: d1: " << ( getValue(d1_check_s) == 0 ? "ok" : "FAIL" ) << endl;
cerr << myname << ": check depend OFF: d2: " << ( getValue(d2_check_s) == -50 ? "ok" : "FAIL" ) << endl;
// set depend 1
setValue(depend_c, 1);
cerr << myname << ": check depend ON: d1: " << ( getValue(d1_check_s) == test_val ? "ok" : "FAIL" ) << endl;
cerr << myname << ": check depend ON: d2: " << ( getValue(d2_check_s) == test_val ? "ok" : "FAIL" ) << endl;
}
// -----------------------------------------------------------------------------
void TestProc::test_undefined_state()
{
// ---------------- Проверка выставления неопределённого состояния ---------------------
cerr << myname << ": Check undef state..." << endl;
undef ^= true;
si.id = undef_c;
si.node = uniset_conf()->getLocalNode();
cerr << myname << ": set undefined=" << undef << endl;
ui->setUndefinedState( si, undef, getId() );
}
// -----------------------------------------------------------------------------
void TestProc::test_thresholds()
{
// ---------------- Проверка работы порогов ---------------------
cerr << myname << ": Check thresholds..." << endl;
setValue(t_set_c, 0);
cerr << myname << ": check threshold OFF value: " << ( getValue(t_check_s) == 0 ? "ok" : "FAIL" ) << endl;
setValue(t_set_c, 378);
cerr << myname << ": check threshold ON value: " << ( getValue(t_check_s) == 1 ? "ok" : "FAIL" ) << endl;
cerr << myname << ": ask threshold and check.. " << endl;
try
{
setValue(t_set_c, 0);
UniSetTypes::ThresholdId tid = 100;
ui->askThreshold( t_set_c, tid, UniversalIO::UIONotify, 10, 20 );
IONotifyController_i::ThresholdInfo ti = ui->getThresholdInfo(t_set_c, tid);
cerr << myname << ": ask OFF threshold: " << ( ti.state == IONotifyController_i::NormalThreshold ? "ok" : "FAIL" ) << endl;
setValue(t_set_c, 25);
ti = ui->getThresholdInfo(t_set_c, tid);
cerr << myname << ": ask ON threshold: " << ( ti.state == IONotifyController_i::HiThreshold ? "ok" : "FAIL" ) << endl;
}
catch( const Exception& ex )
{
mylog2 << myname << ": CHECK 'ask and get threshold' FAILED: " << ex << endl;
}
}
// -----------------------------------------------------------------------------
void TestProc::test_loglevel()
{
lit++;
if( lit == loglevels.end() )
lit = loglevels.begin();
cerr << "SET LOGLEVEL: [" << (int)(*lit) << "] " << (*lit) << endl;
setValue(log_c, (*lit));
askTimer(tmLogControl, checkLogTime);
}
// -----------------------------------------------------------------------------
void TestProc::mbThread()
{
mylog9 << myname << "ModbusSlave started " << mbIP << ":" << mbPort << endl;
mylog9 << myname << "(mbThread): run tcpserver.." << endl;
ModbusRTU::ModbusAddr mba(mbADDR);
auto vaddr = mbslave->addr2vaddr(mba);
mbslave->run( vaddr, false ); // true - создаёт поток
mylog9 << myname << "ModbusSlave stopped.." << endl;
}
// -------------------------------------------------------------------------
ModbusRTU::mbErrCode TestProc::writeOutputSingleRegister( ModbusRTU::WriteSingleOutputMessage& query,
ModbusRTU::WriteSingleOutputRetMessage& reply )
{
mylog9 << myname << "(writeOutputSingleRegister): " << query << endl;
reply.set(query.start, query.data);
return ModbusRTU::erNoError;
}
// -----------------------------------------------------------------------------
#ifndef TestProc_H_
#define TestProc_H_
// -----------------------------------------------------------------------------
#include <vector>
#include "Debug.h"
#include "TestProc_SK.h"
#include "modbus/ModbusTCPServerSlot.h"
// -----------------------------------------------------------------------------
class TestProc:
public TestProc_SK
{
public:
TestProc( UniSetTypes::ObjectId id, xmlNode* confnode = UniSetTypes::uniset_conf()->getNode("TestProc") );
virtual ~TestProc();
protected:
TestProc();
enum Timers
{
tmChange,
tmCheckWorking,
tmCheck,
tmLogControl
};
virtual void step();
virtual void sensorInfo( const UniSetTypes::SensorMessage* sm );
virtual void timerInfo( const UniSetTypes::TimerMessage* tm );
virtual void sysCommand( const UniSetTypes::SystemMessage* sm );
void test_depend();
void test_undefined_state();
void test_thresholds();
void test_loglevel();
private:
bool state;
bool undef;
std::vector<Debug::type> loglevels;
std::vector<Debug::type>::iterator lit;
std::shared_ptr<ModbusTCPServerSlot> mbslave;
/*! обработка 0x06 */
ModbusRTU::mbErrCode writeOutputSingleRegister( ModbusRTU::WriteSingleOutputMessage& query,
ModbusRTU::WriteSingleOutputRetMessage& reply );
std::shared_ptr< ThreadCreator<TestProc> > mbthr;
void mbThread();
};
// -----------------------------------------------------------------------------
#endif // TestProc_H_
// -----------------------------------------------------------------------------
#include <string>
#include "Debug.h"
#include "UniSetActivator.h"
#include "SharedMemory.h"
#include "Extensions.h"
#include "TestProc.h"
// --------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// --------------------------------------------------------------------------
int main(int argc, const char** argv)
{
if( argc > 1 && ( strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0 ) )
{
cout << "--confile - Использовать указанный конф. файл. По умолчанию configure.xml" << endl;
SharedMemory::help_print(argc, argv);
return 0;
}
try
{
auto conf = uniset_init(argc, argv);
auto shm = SharedMemory::init_smemory(argc, argv);
if( !shm )
return 1;
auto act = UniSetActivator::Instance();
act->add(shm);
int num = conf->getArgPInt("--numproc", 1);
for( int i = 1; i <= num; i++ )
{
ostringstream s;
s << "TestProc" << i;
cout << "..create " << s.str() << endl;
auto tp = make_shared<TestProc>( conf->getObjectID(s.str()));
// tp->init_dlog(dlog());
act->add(tp);
}
SystemMessage sm(SystemMessage::StartUp);
act->broadcast( sm.transport_msg() );
act->run(false);
return 0;
}
catch( const SystemError& err )
{
ucrit << "(smemory): " << err << endl;
}
catch( const Exception& ex )
{
ucrit << "(smemory): " << ex << endl;
}
catch( const std::exception& e )
{
ucrit << "(smemory): " << e.what() << endl;
}
catch(...)
{
ucrit << "(smemory): catch(...)" << endl;
}
return 1;
}
#!/bin/sh
START=uniset2-start.sh
${START} -f ./mbslave-test --confile ./test.xml --dlog-add-levels level1 --localNode LocalhostNode \
--sm-log-add-levels any $* --sm-run-logserver --TestProc1-run-logserver
../../../Utilities/scripts/uniset2-stop.sh
\ No newline at end of file
../../../conf/test.xml
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
name - название класса
msgcount - сколько сообщений обрабатывается за один раз
sleep_msec - пауза между итерациями в работе процесса
type
====
in - входные регистры (только для чтения)
out - выходные регистры (запись)
-->
<TestProc>
<settings>
<set name="class-name" val="TestProc"/>
<set name="msg-count" val="30"/>
<set name="sleep-msec" val="150"/>
</settings>
<variables>
<item name="changeTime" type="int" default="2000" min="0" comment="change state time" const="1" public="1" />
<item name="checkWorkingTime" type="int" default="3000" min="0" comment="check working time" const="1" public="1" />
<item name="checkTime" type="int" default="3000" min="0" comment="check Working time" const="1" public="1" />
<item name="checkLogTime" type="int" default="2500" min="0" comment="Проверка управления логами" const="1" public="1" />
<item const="1" type="str" public="1" name="mbIP" comment="Modbus ip (slave)" default="localhost"/>
<item const="1" type="int" public="1" name="mbADDR" comment="Modbus slave addr (slave)" default="0x01"/>
<item type="int" public="1" name="mbPort" comment="Modbus port (slave)" default="502"/>
</variables>
<smap>
<!-- name - название переменной в конф. файле -->
<item name="on_s" vartype="in" comment="Тестовый вход" smTestID="1"/>
<item name="lamp_c" vartype="out" comment="Лампочка (тестовый выход)"/>
<!-- проверка работы механизма зависимостей -->
<item name="depend_c" vartype="out" comment="Датчик от которого зависит состояние другого"/>
<item name="d1_check_s" vartype="in" comment="состояние зависимого датчика"/>
<item name="d2_check_s" vartype="in" comment="состояние зависимого датчика"/>
<item name="set_d1_check_s" vartype="out" comment="для выставления датчика"/>
<item name="set_d2_check_s" vartype="out" comment="для выставления датчика"/>
<!-- проверка работы undefined state -->
<item name="undef_c" vartype="out" comment="аналоговый датчик (для проверки undef-состояния)"/>
<item name="check_undef_s" vartype="in" comment="датчик для выставления undef-состояния"/>
<!-- проверка работы threshold-ов -->
<item name="t_set_c" vartype="out" comment="аналоговый датчик (для выставления порога)"/>
<item name="t_check_s" vartype="in" comment="датчик для проверки срабатывания"/>
<!-- Проверка управления логами -->
<item name="log_c" vartype="out" comment="аналоговый датчик для выставления уровня логов"/>
<item name="log_s" vartype="in" comment="датчик для управления логами" loglevel="1"/>
</smap>
<msgmap>
</msgmap>
</TestProc>
../../../Utilities/scripts/uniset2-functions.sh
\ No newline at end of file
../../../Utilities/scripts/uniset2-start.sh
\ No newline at end of file
SUBDIR=SMemoryTest SUBDIRS=SMemoryTest MBSlaveTest
if HAVE_TESTS if HAVE_TESTS
noinst_PROGRAMS = tests tests_with_conf tests_with_sm sm_perf_test noinst_PROGRAMS = tests tests_with_conf tests_with_sm sm_perf_test
......
...@@ -16,7 +16,7 @@ namespace UTCPCore ...@@ -16,7 +16,7 @@ namespace UTCPCore
// Buffer class - allow for output buffering such that it can be written out into async pieces // Buffer class - allow for output buffering such that it can be written out into async pieces
struct Buffer struct Buffer
{ {
unsigned char* data; unsigned char* data = { 0 };
ssize_t len; ssize_t len;
ssize_t pos; ssize_t pos;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <unordered_map> #include <unordered_map>
#include <type_traits> #include <type_traits>
#include <tuple> #include <tuple>
#include "UTCPCore.h"
template<typename... Args> template<typename... Args>
class VMon class VMon
...@@ -19,6 +20,18 @@ using namespace std; ...@@ -19,6 +20,18 @@ using namespace std;
int main( int argc, const char** argv ) int main( int argc, const char** argv )
{ {
unsigned char dat[] = { '1', '2', '3' ,'4' };
// UTCPCore::Buffer* buf = new UTCPCore::Buffer( dat, 0 );
UTCPCore::Buffer* buf = new UTCPCore::Buffer( dat, 3 );
// if( buf->nbytes() == 0 )
// delete buf;
cout << "buf: " << buf->dpos() << endl;
delete buf;
// VMon<int,double,char> vmon; // VMon<int,double,char> vmon;
// cout << std::get<0>(vmon.m_tuple).size() << endl; // cout << std::get<0>(vmon.m_tuple).size() << endl;
......
...@@ -191,6 +191,12 @@ extensions/tests/SMemoryTest/test.xml ...@@ -191,6 +191,12 @@ extensions/tests/SMemoryTest/test.xml
extensions/tests/SMemoryTest/TestProc.cc extensions/tests/SMemoryTest/TestProc.cc
extensions/tests/SMemoryTest/TestProc.h extensions/tests/SMemoryTest/TestProc.h
extensions/tests/SMemoryTest/testproc.src.xml extensions/tests/SMemoryTest/testproc.src.xml
extensions/tests/SMemoryTest/Makefile.am
extensions/tests/MBSlaveTest/mbslave-test.cc
extensions/tests/MBSlaveTest/test.xml
extensions/tests/MBSlaveTest/TestProc.cc
extensions/tests/MBSlaveTest/TestProc.h
extensions/tests/MBSlaveTest/testproc.src.xml
extensions/tests/Makefile.am extensions/tests/Makefile.am
extensions/tests/test.xml extensions/tests/test.xml
extensions/tests/test_calibration.cc extensions/tests/test_calibration.cc
......
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