Commit 2a7ac403 authored by Pavel Vainerman's avatar Pavel Vainerman

backported to p8 as 2.7-alt13.M80P.14 (with rpmbph script)

parents 55d31016 6dcbb92d
see git changelog
----
json.hpp - Niels Lohmann https://github.com/nlohmann/json
......@@ -11,24 +11,21 @@
- "продумать" функцию key()... может наложить ограничение на диапазон id..
- uniset-codegen: сделать в src.xml <description> и генерировать на его основе описание класса (нужно ли)
- встроить различные сигналы (sigc).. в ModbusExchange и другие классы..
- uniset-codegen: дописать функцию help со всеми параметрами для _SK, тесты
- uniset-codegen: добавить в генерируемую документацию значения по умолчанию..
- uniset-codegen: добавить возможность переопределять привязку из командной строки
- uniset-codegen: добавить ключ --gen-sensor-name для генерирования name_Item.. (чтобы можно было в логах использовать текстовые названия)
- uniset-codegen: перенести инициализацию полей в header (c++11) и "разгрузить конструкторы"
- unetudp: добавить возможость привязать номера текущего посылаемого и принимаемого пакетов к датчику
- встроить различные сигналы (sigc).. в ModbusExchange и другие классы..
- ModbusMaster: встроить возможность задать 'pulsar' (регистр сердцебиения)
- ТЕСТЫ! ТЕСТЫ! ТЕСТЫ!
- Перевести взаимодействие PassiveObject <--> ProxyManager на shared_ptr (или weak_ptr). // нужно ли
uniset-codegen: добавить ключ --gen-sensor-name для генерирования name_Item.. (чтобы можно было в логах использовать текстовые названия)
uniset-codegen: перенести инициализацию полей в header (c++11) и "разгрузить конструкторы"
- Сделать диапазонные пороги в IOBase и SM (т.е. "1" когда min >= val <= max ).
SQL:
......@@ -67,8 +64,6 @@ IOBase:
Либо стоит всё-таки ввести свой тип данных value_t для хранимых значений, чтобы спокойно работать в x86_64 и x86_32
при этом скрыв детали реализации. А возможно в последствии наложить какие-то ограничения на этот тип
- timeout_t getSharedMemoryReadyTimeout()!
ModbusSlave: подумать насчёт оптимизации по скорости (вместо поиска по RegMap, сделать массив на 65535 регистров или map-ов по номеру функции,
всего 65kB памяти).
......@@ -93,7 +88,7 @@ DB: Сделать регулируемый буфер на INSERT-ы БД, чт
timeout_t перевести всё на chrono.. чтобы использовать setTimeout( 2msec );
ВОЗМОЖНО СТОИТ:
Уйти от использования libxml2,DebugLog ==> и применять одну библиотеку libpoco (http://pocoproject.org/documentation/index.html)
Уйти от использования libxml2,DebugLog ==> и применять всё из libpoco (http://pocoproject.org/documentation/index.html)
или всё-таки на boost?
<<<<<<< HEAD
......@@ -116,7 +111,7 @@ lock-free: mentomic, libcds
version 3
=========
- подумать нужен ли нам где-то ZeroMQ (zerorpc) (вместо omniORB?)
- (или) подумать может стоит перейти на использование ICE вместо CORBA
- (или) подумать может стоит перейти на использование ICE вместо CORBA (libIce не собирается под aarch!)
Перепроектировать классы [ObjectRepository, UInterface, ORepHelpers] с целью выработки абстрактного интерфейса
UResolver (или ObjectRepository) позволяющего манипулировать CORBA-ссылками на объекты, но по возможности
......
......@@ -26,7 +26,7 @@
Name: libuniset2
Version: 2.7
Release: alt12.M80P.13
Release: alt13.M80P.14
Summary: UniSet - library for building distributed industrial control systems
License: LGPL
......@@ -546,9 +546,13 @@ rm -f %buildroot%_docdir/%oname/html/*.md5
# history of current unpublished changes
%changelog
* Wed Jul 11 2018 Pavel Vainerman <pv@altlinux.ru> 2.7-alt12.M80P.13
* Thu Aug 02 2018 Pavel Vainerman <pv@altlinux.ru> 2.7-alt13.M80P.14
- backport to ALTLinux p8 (by rpmbph script)
* Thu Aug 02 2018 Pavel Vainerman <pv@altlinux.ru> 2.7-alt14
- remove deprecated classes
- (SM): fixed bug 'uninitialized time value'
* Wed Jul 11 2018 Pavel Vainerman <pv@altlinux.ru> 2.7-alt13
- (UActivator): refactoring the program termination process
- minor fixes
......
/*
* 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/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
//----------------------------------------------------------------------------
# ifndef CallbackTimer_H_
# define CallbackTimer_H_
//----------------------------------------------------------------------------
#include <list>
#include "Exceptions.h"
#include "ThreadCreator.h"
#include "PassiveTimer.h"
//-----------------------------------------------------------------------------
namespace uniset
{
class LimitTimers:
public uniset::Exception
{
public:
LimitTimers(): Exception("LimitTimers") {}
/*! Конструктор позволяющий вывести в сообщении об ошибке дополнительную информацию err */
LimitTimers(const std::string& err): Exception(err) {}
};
//----------------------------------------------------------------------------------------
/*!
* \brief Таймер
* \author Pavel Vainerman
* \par
* Создает поток, в котором происходит отсчет тактов (10ms). Позволяет заказывать до CallbackTimer::MAXCallbackTimer таймеров.
* При срабатывании будет вызвана указанная функция с указанием \b Id таймера, который сработал.
* Функция обратного вызова должна удовлетворять шаблону CallbackTimer::Action.
* Пример создания таймера:
*
\code
class MyClass
{
public:
void Time(size_t id){ cout << "Timer id: "<< id << endl;}
};
MyClass* rec = new MyClass();
...
CallbackTimer<MyClass> *timer1 = new CallbackTimer<MyClass>(rec);
timer1->add(1, &MyClass::Time, 1000);
timer1->add(5, &MyClass::Time, 1200);
timer1->run();
\endcode
*
* \note Каждый экземпляр класса CallbackTimer создает поток, поэтому \b желательно не создавать больше одного экземпляра,
* для одного процесса (чтобы не порождать много потоков).
*
* \todo Можно уже переписать с использованием c++11 и далее..
*/
template <class Caller>
class CallbackTimer
// public PassiveTimer
{
public:
/*! Максимальное количество таймеров */
static const size_t MAXCallbackTimer = 20;
/*! прототип функции вызова */
typedef void(Caller::* Action)( size_t id );
CallbackTimer(Caller* r, Action a);
~CallbackTimer();
// Управление таймером
void run(); /*!< запуск таймера */
void terminate(); /*!< остановка */
// Работа с таймерами (на основе интерфейса PassiveTimer)
void reset(size_t id); /*!< перезапустить таймер */
void setTiming(size_t id, timeout_t timrMS); /*!< установить таймер и запустить */
timeout_t getInterval(size_t id); /*!< получить интервал, на который установлен таймер, в мс */
timeout_t getCurrent(size_t id); /*!< получить текущее значение таймера */
/*! добавление нового таймера.
* throw(uniset::LimitTimers)
*/
void add( size_t id, timeout_t timeMS );
/*! удаление таймера */
void remove( size_t id );
protected:
CallbackTimer();
void work();
void startTimers();
void clearTimers();
private:
typedef CallbackTimer<Caller> CBT;
friend class ThreadCreator<CBT>;
Caller* cal;
Action act;
ThreadCreator<CBT>* thr;
bool terminated;
struct TimerInfo
{
TimerInfo(size_t id, PassiveTimer& pt):
id(id), pt(pt) {}
size_t id;
PassiveTimer pt;
};
typedef std::list<TimerInfo> TimersList;
TimersList lst;
// функция-объект для поиска по id
struct FindId_eq: public std::unary_function<TimerInfo, bool>
{
FindId_eq(const size_t id): id(id) {}
inline bool operator()(const TimerInfo& ti) const
{
return ti.id == id;
}
size_t id;
};
};
//----------------------------------------------------------------------------------------
#include "CallbackTimer.tcc"
//----------------------------------------------------------------------------------------
} // end of uniset namespace
//----------------------------------------------------------------------------------------
# endif //CallbackTimer_H_
/*
* 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/>.
*/
// --------------------------------------------------------------------------
/*! \file
* \author Pavel Vainerman
*/
// --------------------------------------------------------------------------
# ifndef CallbackTimer_TCC_H_
# define CallbackTimer_TCC_H_
// --------------------------------------------------------------------------
#include <unistd.h>
#include <sstream>
#include "CallbackTimer.h"
// ------------------------------------------------------------------------------------------
//template <class Caller> class uniset::CallbackTimer;
// ------------------------------------------------------------------------------------------
/*! Создание таймера
\param r - указатель на заказчика
*/
template <class Caller>
CallbackTimer<Caller>::CallbackTimer( Caller* r, CallbackTimer<Caller>::Action a ):
cal(r),
act(a),
terminated(false)
{
thr = new ThreadCreator<CallbackTimer>(this, &CallbackTimer<Caller>::work);
}
// ------------------------------------------------------------------------------------------
template <class Caller>
CallbackTimer<Caller>::CallbackTimer():
cal(nullptr),
terminated(false)
{
thr = new ThreadCreator<CallbackTimer>(this, &CallbackTimer<Caller>::work);
}
// ------------------------------------------------------------------------------------------
template <class Caller>
CallbackTimer<Caller>::~CallbackTimer()
{
terminate();
clearTimers();
delete thr;
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::work()
{
terminated = false;
while( !terminated )
{
usleep(UniSetTimer::MinQuantityTime);
for( typename TimersList::iterator li=lst.begin(); li!=lst.end(); ++li )
{
if( li->pt.checkTime() )
{
(cal->*act)( li->id );
li->pt.reset();
}
}
}
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::run()
{
if( !terminated )
terminate();
startTimers();
// PosixThread::start(static_cast<PosixThread*>(this));
thr->start();
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::terminate()
{
// timeAct = 0;
terminated = true;
//usleep(1000);
std::this_thread::sleep_for(std::chrono::microseconds(1));
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::add(size_t id, timeout_t timeMS )
{
if( lst.size() >= MAXCallbackTimer )
{
std::ostringstream err;
err << "CallbackTimers: exceeded the maximum number of timers (" << MAXCallbackTimer << ")";
throw uniset::LimitTimers(err.str());
}
PassiveTimer pt(timeMS);
TimerInfo ti(id, pt);
lst.push_back(ti);
// lst[id] = ti;
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::remove( size_t id )
{
// STL - способ поиска
typename TimersList::iterator li= find_if(lst.begin(),lst.end(),FindId_eq(id));
if( li!=lst.end() )
lst.erase(li);
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::startTimers()
{
for( typename TimersList::iterator li=lst.begin(); li!=lst.end(); ++li)
{
li->pt.reset();
}
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::clearTimers()
{
lst.clear();
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::reset( size_t id )
{
typename TimersList::iterator li= find_if(lst.begin(),lst.end(),FindId_eq(id));
if( li!=lst.end() )
li->pt.reset();
}
// ------------------------------------------------------------------------------------------
template <class Caller>
void CallbackTimer<Caller>::setTiming( size_t id, timeout_t timeMS )
{
typename TimersList::iterator li= find_if(lst.begin(),lst.end(),FindId_eq(id));
if( li!=lst.end() )
li->pt.setTimer(timeMS);
}
// ------------------------------------------------------------------------------------------
template <class Caller>
timeout_t CallbackTimer<Caller>::getInterval( size_t id )
{
typename TimersList::iterator li= find_if(lst.begin(),lst.end(),FindId_eq(id));
if( li!=lst.end() )
return li->pt.getInterval();
return UniSetTimer::WaitUpTime;
}
// ------------------------------------------------------------------------------------------
template <class Caller>
timeout_t CallbackTimer<Caller>::getCurrent( size_t id )
{
typename TimersList::iterator li= find_if(lst.begin(),lst.end(),FindId_eq(id));
if( li!=lst.end() )
return li->pt.getCurrent();
return UniSetTimer::WaitUpTime;
}
// ------------------------------------------------------------------------------------------
# endif //CallbackTimer_TCC_H_
......@@ -289,19 +289,7 @@ namespace uniset
USensorInfo( USensorInfo&& ) = default;
USensorInfo& operator=(USensorInfo&& ) = default;
USensorInfo(): d_value(1), d_off_value(0)
{
d_si.id = uniset::DefaultObjectId;
d_si.node = uniset::DefaultObjectId;
default_val = 0;
value = default_val;
real_value = default_val;
dbignore = false;
undefined = false;
blocked = false;
supplier = uniset::DefaultObjectId;
}
USensorInfo();
virtual ~USensorInfo() {}
USensorInfo(IOController_i::SensorIOInfo& r);
......
......@@ -590,7 +590,27 @@ IOController::USensorInfo::operator=(IOController_i::SensorIOInfo& r)
(*this) = r;
return *this;
}
// ----------------------------------------------------------------------------------------
IOController::USensorInfo::USensorInfo(): d_value(1), d_off_value(0)
{
d_si.id = uniset::DefaultObjectId;
d_si.node = uniset::DefaultObjectId;
default_val = 0;
value = default_val;
real_value = default_val;
dbignore = false;
undefined = false;
blocked = false;
supplier = uniset::DefaultObjectId;
// стоит ли выставлять текущее время
// Мы теряем возможность понять (по tv_sec=0),
// что значение ещё ни разу никем не менялось
auto tm = uniset::now_to_timespec();
tv_sec = tm.tv_sec;
tv_nsec = tm.tv_nsec;
}
// ----------------------------------------------------------------------------------------
IOController::USensorInfo&
IOController::USensorInfo::operator=(IOController_i::SensorIOInfo* r)
{
......
......@@ -18,7 +18,6 @@ test_hourglass.cc \
test_delaytimer.cc \
test_unixml.cc \
test_sscanf_hex.cc \
test_callbacktimer.cc \
test_trigger.cc \
test_triggerOR.cc \
test_triggerAND.cc \
......
#include <catch.hpp>
#include <atomic>
#include "CallbackTimer.h"
#include "UniSetTypes.h"
using namespace std;
using namespace uniset;
class MyTestClass
{
public:
MyTestClass(): num1(0), num2(0), num3(0) {}
~MyTestClass() {}
void Time( size_t id )
{
if( id == 1 )
num1++;
else if( id == 2 )
num2++;
else if( id == 3 )
num3++;
}
inline int getNum1()
{
return num1;
}
inline int getNum2()
{
return num2;
}
inline int getNum3()
{
return num3;
}
private:
std::atomic_int num1;
std::atomic_int num2;
std::atomic_int num3;
};
TEST_CASE("CallbackTimer", "[CallbackTimer]" )
{
SECTION("Basic tests")
{
MyTestClass tc;
CallbackTimer<MyTestClass> tmr(&tc, &MyTestClass::Time);
tmr.add(1, 50 );
tmr.add(2, 150 );
tmr.add(3, 300 );
tmr.run();
msleep(60);
REQUIRE( tc.getNum1() >= 1 );
REQUIRE( tc.getNum2() == 0 );
REQUIRE( tc.getNum3() == 0 );
msleep(110);
REQUIRE( tc.getNum1() >= 2 );
REQUIRE( tc.getNum2() >= 1 );
REQUIRE( tc.getNum3() == 0 );
msleep(210);
REQUIRE( tc.getNum1() >= 5 );
REQUIRE( tc.getNum2() >= 2 );
REQUIRE( tc.getNum3() == 1 );
tmr.remove(1);
msleep(60);
REQUIRE( tc.getNum1() >= 6 );
tmr.terminate();
REQUIRE( tc.getNum2() >= 2 );
REQUIRE( tc.getNum3() >= 1 );
}
SECTION("other tests")
{
MyTestClass tc;
CallbackTimer<MyTestClass> tmr(&tc, &MyTestClass::Time);
unsigned int i = 0;
for( ; i < tmr.MAXCallbackTimer; i++ )
tmr.add(i, 100 );
REQUIRE_THROWS_AS( tmr.add(++i, 100), uniset::LimitTimers );
}
}
......@@ -287,7 +287,6 @@ include/modbus/ModbusTCPServer.h
include/modbus/ModbusTCPServerSlot.h
include/modbus/ModbusTCPSession.h
include/modbus/ModbusTypes.h
include/CallbackTimer.h
include/ComPort.h
include/ComPort485F.h
include/Configuration.1.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