Commit 618e6fba authored by Pavel Vainerman's avatar Pavel Vainerman

make style, fix docs

parent 1a629d75
......@@ -76,7 +76,7 @@ int getRawValue( const string& args, UInterface& ui );
int getTimeChange( const string& args, UInterface& ui );
int getState( const string& args, UInterface& ui );
int getCalibrate( const string& args, UInterface& ui );
int oinfo(const string& args, UInterface& ui , const string& userparam );
int oinfo(const string& args, UInterface& ui, const string& userparam );
int apiRequest( const string& args, UInterface& ui, const string& query );
void sendText( const string& args, UInterface& ui, const string& txt, int mtype );
// --------------------------------------------------------------------------
......@@ -303,6 +303,7 @@ int main(int argc, char** argv)
commandToAll(conf->getControllersSection(), rep, (Command)cmd);
commandToAll(conf->getObjectsSection(), rep, (Command)cmd);
}
return 0;
case 'r': //--configure
......@@ -331,6 +332,7 @@ int main(int argc, char** argv)
if( verb )
cout << "(finish): done" << endl;
}
return 0;
case 'l': //--logrotate
......@@ -386,7 +388,7 @@ int main(int argc, char** argv)
std::string consumers(optarg);
ostringstream txt;
if( checkArg(optind+1, argc, argv) == 0 )
if( checkArg(optind + 1, argc, argv) == 0 )
{
if( !quiet )
cerr << "admin(sendText): Unknown 'text'. Use: id,name,name2@nodeX mtype text" << endl;
......@@ -394,7 +396,7 @@ int main(int argc, char** argv)
return 1;
}
for( int i=optind+1; i<argc; i++ )
for( int i = optind + 1; i < argc; i++ )
{
if( checkArg(i, argc, argv) == 0 )
break;
......@@ -669,7 +671,7 @@ int setValue( const string& args, UInterface& ui )
if( verb )
cout << "====== setValue ======" << endl;
for( auto && it : sl )
for( auto&& it : sl )
{
try
{
......@@ -738,7 +740,7 @@ int getValue( const string& args, UInterface& ui )
size_t num = 0;
for( auto && it : sl )
for( auto&& it : sl )
{
try
{
......@@ -817,7 +819,7 @@ int getCalibrate( const std::string& args, UInterface& ui )
if( !quiet )
cout << "====== getCalibrate ======" << endl;
for( auto && it : sl )
for( auto&& it : sl )
{
if( it.si.node == DefaultObjectId )
it.si.node = conf->getLocalNode();
......@@ -867,7 +869,7 @@ int getRawValue( const std::string& args, UInterface& ui )
if( !quiet )
cout << "====== getRawValue ======" << endl;
for( auto && it : sl )
for( auto&& it : sl )
{
if( it.si.node == DefaultObjectId )
it.si.node = conf->getLocalNode();
......@@ -912,7 +914,7 @@ int getTimeChange( const std::string& args, UInterface& ui )
if( !quiet )
cout << "====== getChangedTime ======" << endl;
for( auto && it : sl )
for( auto&& it : sl )
{
if( it.si.node == DefaultObjectId )
it.si.node = conf->getLocalNode();
......@@ -1069,7 +1071,7 @@ int oinfo(const string& args, UInterface& ui, const string& userparam )
auto conf = uniset_conf();
auto sl = uniset::getObjectsList( args, conf );
for( auto && it : sl )
for( auto&& it : sl )
{
if( it.node == DefaultObjectId )
it.node = conf->getLocalNode();
......@@ -1103,7 +1105,7 @@ int apiRequest( const string& args, UInterface& ui, const string& query )
// if( verb )
// cout << "apiRequest: query: " << query << endl;
for( auto && it : sl )
for( auto&& it : sl )
{
if( it.node == DefaultObjectId )
it.node = conf->getLocalNode();
......@@ -1137,7 +1139,7 @@ void sendText( const string& args, UInterface& ui, const string& txt, int mtype
cout << "mtype=" << mtype << " txt: " << txt << endl;
for( auto && it : sl )
for( auto&& it : sl )
{
if( it.node == DefaultObjectId )
it.node = conf->getLocalNode();
......
......@@ -29,11 +29,11 @@ MBSlave::MBSlave(const std::unordered_set<ModbusAddr>& _vaddr, const std::string
// if( replyTimeout <= 0 )
// replyTimeout = 2000;
// if( verbose )
// cout << "(init): "
// << " addr=" << ModbusServer::vaddr2str(vaddr)
// << " dev=" << dev
// << " speed=" << speed;
// if( verbose )
// cout << "(init): "
// << " addr=" << ModbusServer::vaddr2str(vaddr)
// << " dev=" << dev
// << " speed=" << speed;
rscomm = new ModbusRTUSlaveSlot(dev, use485);
......
......@@ -102,7 +102,7 @@ struct Interval
using time_point = std::chrono::time_point<std::chrono::steady_clock>;
Interval()
:tmStart(std::chrono::steady_clock::now())
: tmStart(std::chrono::steady_clock::now())
{}
uint64_t microseconds()
......@@ -322,6 +322,7 @@ int main( int argc, char** argv )
}
break;
#if 0
case 'g':
{
if( cmd == cmdNOP )
......@@ -342,6 +343,7 @@ int main( int argc, char** argv )
}
break;
#endif
case 'v':
verb = 1;
break;
......@@ -766,6 +768,7 @@ int main( int argc, char** argv )
Interval i;
mb.fileTransfer( slaveaddr, reg, tofile, tout);
if( verb )
cout << i.microseconds() << " ms" << endl;
}
......
......@@ -90,7 +90,7 @@ struct Interval
using time_point = std::chrono::time_point<std::chrono::steady_clock>;
Interval()
:tmStart(std::chrono::steady_clock::now())
: tmStart(std::chrono::steady_clock::now())
{}
uint64_t microseconds()
......
......@@ -60,7 +60,7 @@ int main( int argc, char** argv )
std::list<ExtInfo> l;
for( auto && it : lst )
for( auto&& it : lst )
{
UniversalIO::IOType t = conf->getIOType( it.si.id );
......
......@@ -32,9 +32,10 @@ AC_ENABLE_SHARED(yes)
AC_ENABLE_STATIC(no)
AM_PROG_LIBTOOL
ASTYLE_OPT="-A1 -T -C -S -N -L -w -Y -M -f -p --mode=c --lineend=linux --align-reference=type --align-pointer=type --suffix=none --style=ansi"
ASTYLE_OPT="-A1 -T -C -S -L -w -N -Y -M -f -p --mode=c --lineend=linux --align-reference=type --align-pointer=type --suffix=none --style=ansi --convert-tabs -s4"
AC_SUBST(ASTYLE_OPT)
# Checks for libraries.
PKG_CHECK_MODULES(XML, libxml-2.0)
PKG_CHECK_MODULES(OMNI, omniORB4)
......
......@@ -13,22 +13,21 @@
- \ref sec_Concept_Process
\section sec_Concept_Object Объект
\section sec_Concept_Object Объект
В разных местах описаний, в зависимости от контекста,
под "объектом" подразумевается либо объект класса так или иначе наследующегося
от базового класса библиотеки UniSetObject, либо
некий концептуальный программный объект способный
получать и обрабатывать сообщения.
\section sec_Concept_ObjectTypes Основные типы объектов
\section sec_Concept_ObjectTypes Основные типы объектов
В библиотеке произведено условное деление на следующие типы объектов:
- (простые) объекты - наследуются от класса UniSetObject
- контроллеры - являются наследниками класса IOController
- сервисы - являются наследниками специальных классов
- узлы - в строгом смысле, не являются объектами,
но обладают уникальным идентификатором.
- (простые) объекты - наследуются от класса UniSetObject
- контроллеры - являются наследниками класса IOController
- сервисы - являются наследниками специальных классов
- узлы - в строгом смысле, не являются объектами, но обладают уникальным идентификатором.
\section sec_Concept_Message Сообщения
\section sec_Concept_Message Сообщения
Вся система взаимодействия между объектами в основном
построена на использовании сообщений (передаваемых
путём удаленного вызова специальных функций,
......@@ -53,7 +52,7 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
\endcode
\section sec_Concept_ObjectId Идентификатор объекта
\section sec_Concept_ObjectId Идентификатор объекта
Каждый объект, которому необходимо взаимодействовать с другими объектами
(в том числе датчиками см. \ref sec_Concept_Sensor) должен обладать уникальным
идентификатором. В качестве идентификатора выступает любое число типа \b UniSetTypes::ObjectId.
......@@ -74,7 +73,7 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
\code
<Configurations>
...
<ObjectsMap idfromfile="0">
<ObjectsMap idfromfile="0">
<nodes port="2809">
<item name="LocalhostNode" alias="" textname="Локальный узел" ip="127.0.0.1" dbserver=""/>
<item name="Node2" alias="" textname="Локальный узел" ip="127.0.0.1" dbserver=""/>
......@@ -100,7 +99,7 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
<item name="TestProc1"/>
<item name="TestProc2"/>
</objects>
</ObjectsMap>
</ObjectsMap>
...
</Configurations>
\endcode
......@@ -130,7 +129,7 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
\code
<Configurations>
...
<ObjectsMap idfromfile="1">
<ObjectsMap idfromfile="1">
<nodes port="2809">
<item id="1000" name="LocalhostNode" alias="" textname="Локальный узел" ip="127.0.0.1" dbserver=""/>
<item id="1001" name="Node2" alias="" textname="Локальный узел" ip="127.0.0.1" dbserver=""/>
......@@ -156,7 +155,7 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
<item id="200" name="TestProc1"/>
<item id="201" name="TestProc2"/>
</objects>
</ObjectsMap>
</ObjectsMap>
...
</Configurations>
\endcode
......@@ -166,17 +165,17 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
не сложными скриптами).
\section sec_Concept_Repository Репозиторий объектов
\section sec_Concept_Repository Репозиторий объектов
\section sec_Concept_Sensor Датчик
\section sec_Concept_Sensor Датчик
Датчик - это одно из базовых понятий при построении систем на основе libuniset.
Датчик - это информационная единица. Практически любая информация
(о событиях, о состоянии того или иного процесса, объекта, сообщение оператору и т.п.)
передаётся через состояние "датчика". В библиотеке предусмотрено четыре типа датчиков.
- DI - UniversalIO::DigitalInput - дискретный вход
- DO - UniversalIO::DigitalOutput - дискретный выход
- AI - UniversalIO::AnalogInput - аналоговый вход
- AO - UniversalIO::AnalogOutput - аналоговый выход
- DI - UniversalIO::DigitalInput - дискретный вход
- DO - UniversalIO::DigitalOutput - дискретный выход
- AI - UniversalIO::AnalogInput - аналоговый вход
- AO - UniversalIO::AnalogOutput - аналоговый выход
Исходно данные типы используются непосредственно процессами ввода/вывода.
"Выходы"(DO,AO) - это, команды "от системы управления"
......@@ -191,7 +190,7 @@ UniSetTypes::Message::TheLastFieldOfTypeOfMessage.
на передачу цифровой информации (не текстовой).
Например CAN, ModbusRTU, ModbusTCP и т.п.
\section sec_Concept_Process Процесс
\section sec_Concept_Process Процесс
Под процессом в документации чаще всего подразумевается системный
процесс (запущенная программа) выполняющий те или иные функции управления
и обменивающийся для этого с другими процессами сообщениями или
......
/*! \page ConfigurationPage Конфигурирование системы
- \ref ConfigurationPage_secCommon
- \ref ConfigurationPage_secOmniORB
- \ref ConfigurationPage_secCommon
- \ref ConfigurationPage_secOmniORB
\section ConfigurationPage_secCommon Общее описание
\section ConfigurationPage_secCommon Общее описание
Для конфигурирования системы используется файл (обычно "configure.xml").
Конфигурация является глобальным объектом. Для получения доступа к ней используется функция auto conf = uniset_conf();
До начала работы, обычно в функции main(), конфигурация должна быть инициализирована при помощи функции uniset_init().
При этом третий параметр, указывающий название конфигурационного файла, является не обязательным.
По умолчанию обрабатывается аргумент командной строки --confile filename.
Для конфигурирования системы используется файл (обычно "configure.xml").
Конфигурация является глобальным объектом. Для получения доступа к ней используется функция auto conf = uniset_conf();
До начала работы, обычно в функции main(), конфигурация должна быть инициализирована при помощи функции uniset_init().
При этом третий параметр, указывающий название конфигурационного файла, является не обязательным.
По умолчанию обрабатывается аргумент командной строки --confile filename.
\code
...
......@@ -23,7 +23,6 @@ int main(int argc, char **argv)
uniset_init(argc, argv, "configure.xml");
...
...
}
catch(Exception& ex )
{
......@@ -33,28 +32,27 @@ int main(int argc, char **argv)
{
cerr << "Неизвестное исключение!!!!"<< endl;
}
...
...
}
\endcode
\section ConfigurationPage_secOmniORB Конфигурирование OmniORB
Для возможности задать напрямую параметры для omniORB заложена специальная секция <omniORB>.
\section ConfigurationPage_secOmniORB Конфигурирование OmniORB
Для возможности задать напрямую параметры для omniORB заложена специальная секция <omniORB>.
В данную секцию можно записывать любые параметры поддерживаемые библиотекой omniORB.
Формат и название параметров см. документацию по omniORB.
В данную секцию можно записывать любые параметры поддерживаемые библиотекой omniORB.
Формат и название параметров см. документацию по omniORB.
Пример:
Пример:
\code
<omniORB>
<omniORB>
<option name="endPoint" arg="giop:tcp:host1:"/>
<option name="endPoint" arg="giop:tcp:host2:" error_if_not_available="1"/>
</omniORB>
</omniORB>
\endcode
Для параметра 'endPoint' встроена дополнительная проверка доступности указанной адреса.
\warning По умолчанию \b недоступность \b игнорируется, если не указан параметр \a error_if_not_available="1"
Для параметра 'endPoint' встроена дополнительная проверка доступности указанного адреса.
\warning По умолчанию \b недоступность \b игнорируется, если не указан параметр \a error_if_not_available="1"
Помимо этого можно задать параметр \a ignore_checking="1", чтобы не происходило проверки доступности endPoint.
Помимо этого можно задать параметр \a ignore_checking="1", чтобы не происходило проверки доступности endPoint.
*/
\ No newline at end of file
/* OBSOLETE DOC!!!
\page ControlProcessPage Как писать процесс управления
\page ControlProcessPage Как писать процесс управления
- \ref pgCP_secDeclareIDL
- \ref pgCP_secImplementation
- \ref pgCP_secMain
- \ref pgCP_secLT_Object
- \ref pgCP_secRecomendation
- \ref pgCP_secDeclareIDL
- \ref pgCP_secImplementation
- \ref pgCP_secMain
- \ref pgCP_secLT_Object
- \ref pgCP_secRecomendation
Все рядовые процессы управления должны наследоваться от класса UniSetObject.
\par
Все рядовые процессы управления должны наследоваться от класса UniSetObject.
\par
Рассмотрим процесс написания на примере самого простого процесса управления реализующего
две функции \c on() и \c off(). Чтобы эти функции были доступны другим процессам необходимо
объявить интерфейс на языке IDL.
\section pgCP_secDeclareIDL Объявление интерфейса на IDL
\section pgCP_secDeclareIDL Объявление интерфейса на IDL
Как писалось выше процесс управления должен наследоваться UniSetObject, это касается и IDL-интерфейса.
Пример объявления
\code
......@@ -24,8 +24,8 @@
// ------------------------------------------------------------------------------------------
interface TestActiveProcess_i: UniSetObject_i
{
void on();
void off();
void on();
void off();
};
#endif
\endcode
......@@ -37,24 +37,24 @@ interface TestActiveProcess_i: UniSetObject_i
На основе этих файлов вы реализуете свой интерфейс на С++.
\section pgCP_secImplementation Реализация интерфейса на C++
\section pgCP_secImplementation Реализация интерфейса на C++
Необходимо создать класс реализующий объявленый интерфейс. Формирование названия класса и правила наследования
см. \ref UniSetLibStylePage.
\par
Базовые функции интерфейса UniSetObject_i уже реализованы в классе UniSetObject. Поэтому остается только
наследоваться от него и реализовать недостающие функции. В итоге получаем
\code
#ifndef TestActiveProcess_H_
#define TestActiveProcess_H_
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
#include "UniSetObject.h"
#include "TestActiveProcess_i.hh"
// ------------------------------------------------------------------------------------------
class TestActiveProcess:
#ifndef TestActiveProcess_H_
#define TestActiveProcess_H_
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
#include "UniSetObject.h"
#include "TestActiveProcess_i.hh"
// ------------------------------------------------------------------------------------------
class TestActiveProcess:
public POA_TestActiveProcess_i,
public UniSetObject
{
{
public:
// ------- Конструктор с заданием обязательных параметров ---------------
......@@ -79,20 +79,20 @@ interface TestActiveProcess_i: UniSetObject_i
// Сделан protected чтобы нельзя было создать объект класса
// не задав обязательных параметров
TestActiveProcess();
};
};
\endcode
Реализация функций может выглядеть примерно следующим образом:
\code
// ------------------------------------------------------------------------------------------
void TestActiveProcess::TestActiveProcess( UniSetTypes::ObjectId id ):
// ------------------------------------------------------------------------------------------
void TestActiveProcess::TestActiveProcess( UniSetTypes::ObjectId id ):
UniSetObject(id)
{
}
// ------------------------------------------------------------------------------------------
{
}
// ------------------------------------------------------------------------------------------
void TestActiveProcess::processingMessage( UniSetTypes::VoidMessage *msg)
{
void TestActiveProcess::processingMessage( UniSetTypes::VoidMessage *msg)
{
try
{
switch(msg->type)
......@@ -129,11 +129,11 @@ interface TestActiveProcess_i: UniSetObject_i
cout << myname << "(processingMessage): " << ex << endl;
}
catch(...){}
}
// ------------------------------------------------------------------------------------------
}
// ------------------------------------------------------------------------------------------
void TestActiveProcess::askSensors(UniversalIO::UIOCommand cmd)
{
void TestActiveProcess::askSensors(UniversalIO::UIOCommand cmd)
{
try
{
// дискретные датчики
......@@ -148,18 +148,18 @@ interface TestActiveProcess_i: UniSetObject_i
{
cout << myname << ex << endl;
}
}
// ------------------------------------------------------------------------------------------
}
// ------------------------------------------------------------------------------------------
void TestActiveProcess::sigterm( int signo )
{
void TestActiveProcess::sigterm( int signo )
{
cout << myname << "(sigterm): signo " << signo << endl;
askSensors( UniversalIO::UIODontNotify );
}
// ------------------------------------------------------------------------------------------
}
// ------------------------------------------------------------------------------------------
void TestActiveProcess::sysCommand( SystemMessage* sm )
{
void TestActiveProcess::sysCommand( SystemMessage* sm )
{
cout << myname << "(sysCommand): command= "<< sm->command << endl;
switch(sm->command)
{
......@@ -178,20 +178,20 @@ interface TestActiveProcess_i: UniSetObject_i
default:
break;
}
}
// ------------------------------------------------------------------------------------------
}
// ------------------------------------------------------------------------------------------
void TestActiveProcess::sensorInfo( SensorMessage *si )
{
void TestActiveProcess::sensorInfo( SensorMessage *si )
{
cout << myname << "(sensorInfo): name" << conf->oind.getNameById(si->id,si.node) << endl;
}
// ------------------------------------------------------------------------------------------
}
// ------------------------------------------------------------------------------------------
void TestActiveProcess::timerInfo( UniSetTypes::TimerMessage* tm )
{
void TestActiveProcess::timerInfo( UniSetTypes::TimerMessage* tm )
{
cout << myname << "(timerInfo): timerId=" << tm->id << endl;
}
// ------------------------------------------------------------------------------------------
}
// ------------------------------------------------------------------------------------------
\endcode
......@@ -199,16 +199,16 @@ interface TestActiveProcess_i: UniSetObject_i
\code
#include "ObjectsMap.h"
#include "TestActiveProcess.h"
#include "ObjectsActivator.h"
#include "Configuration.h"
// ------------------------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
#include "ObjectsMap.h"
#include "TestActiveProcess.h"
#include "ObjectsActivator.h"
#include "Configuration.h"
// ------------------------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
int main( int argc, char **argv )
{
int main( int argc, char **argv )
{
try
{
conf = new Configuration(argc, (const char**)argv, "configure.xml", (ObjectInfo*)ObjectsMap);
......@@ -230,7 +230,7 @@ interface TestActiveProcess_i: UniSetObject_i
}
return 0;
}
}
\endcode
......@@ -263,8 +263,8 @@ interface TestActiveProcess_i: UniSetObject_i
\endcode
Функция UniSetObject_LT::askTimer() повторяет интерфейс UniversalInterface::askTimer().
Реализация построена, на переопределении функции UniSetObject::callback(), поэтому если поток
не будет создан, таймеры работать не будут.
\sa LT_Object, UniSetObject_LT, ObjectsManager_LT
не будет создан, таймеры работать не будут.
\sa LT_Object, UniSetObject_LT, ObjectsManager_LT
......@@ -282,7 +282,7 @@ interface TestActiveProcess_i: UniSetObject_i
\warning Заказ датчиков может (и должен) происходить \b только после активизации. Ваш процесс НЕ будет доступен
для приема команд и сообщений пока он не активизирован.
\par
\par
Вот вроде и все пока...
*/
\ No newline at end of file
/*! \page DebugPage Описание использования функций отладки
Класс для вывода отладочных сообщений называется DebugStream.
Сообщения могут выводится на экран и в файл, отбираться по
определённым критериям и до определённого уровня.
Класс для вывода отладочных сообщений называется DebugStream.
Сообщения могут выводится на экран и в файл, отбираться по
определённым критериям и до определённого уровня.
- \ref subUsing
- \ref subConf
- \ref subUsing
- \ref subConf
\subsection subUsing Использование
Для использования нужно создать свой объект класса DebugStream или
использовать глобальный объект UniSetTypes::unideb.
Для переключения вывода отладки в файл, используйте функцию logFile(char const *f);
\subsection subUsing Использование
Для использования нужно создать свой объект класса DebugStream или
использовать глобальный объект UniSetTypes::unideb.
Для переключения вывода отладки в файл, используйте функцию logFile(char const *f);
Описание всех имеющихся функций находится в файле DebugStream.h
на английском языке.
Описание всех имеющихся функций находится в файле DebugStream.h
на английском языке.
Функция unideb[...] по умолчанию выводит в строку дату и время.
Функция unideb(...) просто выводит строку (в конец предыдущему потоку).
Функция unideb[...] по умолчанию выводит в строку дату и время.
Функция unideb(...) просто выводит строку (в конец предыдущему потоку).
\par Пример использования:
\code
......@@ -40,8 +40,8 @@
\endcode
Если вы хотите использовать отладочный вывод из критичного к времени
кода, используйте следующую конструкцию:
Если вы хотите использовать отладочный вывод из критичного к времени
кода, используйте следующую конструкцию:
\code
if (unideb.debugging(Debug::INFO)) {
......@@ -50,7 +50,7 @@
\endcode
\subsection subConf Конфигурирование логов
\subsection subConf Конфигурирование логов
Конфигурирование логов можно производить, при помощи файла конфигурации или через командную строку.
Например UniSetTypes::unideb настраивается в конфигурационном файле следующим образом:
......
/* OBSOLETE DOC!!!
\page IOConfigurePage Настройка процессов ввода/вывода
\page IOConfigurePage Настройка процессов ввода/вывода
- \ref pgIOC_secCommon
- \ref pgIOC_secIOTypes
- \ref pgIOC_secAskFile
- \ref pgIOC_secCommon
- \ref pgIOC_secIOTypes
- \ref pgIOC_secAskFile
- \ref pgIOC_secDIO
- \ref pgIOC_secAIO
- \ref pgIOC_secThresholds
- \ref pgIOC_secConsumers
- \ref pgIOC_secSensorMessage
- \ref pgIOC_secAutoGen
- \ref pgIOC_secSensorMessage
- \ref pgIOC_secAutoGen
\section pgIOC_secCommon Общее описание
\section pgIOC_secCommon Общее описание
Процессы ввода/вывода построенные на основе IONotifyContoller-а можно
конфигурировать при помощи настроечного файла (dump-файла). В этом
файле прописываются все "входы" и "выходы" которые опрашивает данный процесс в/в,
а также список "заказчиков" по каждому датчику. Данный файл можно формировать автоматически.
конфигурировать при помощи настроечного файла (dump-файла). В этом
файле прописываются все "входы" и "выходы" которые опрашивает данный процесс в/в,
а также список "заказчиков" по каждому датчику. Данный файл можно формировать автоматически.
\section pgIOC_secIOTypes Возможные типы входов/выходов
- \b DI - дискретный вход
- \b DO - дискретный выход
- \b AI - аналоговый вход
- \b AO - аналоговый выход
\section pgIOC_secIOTypes Возможные типы входов/выходов
- \b DI - дискретный вход
- \b DO - дискретный выход
- \b AI - аналоговый вход
- \b AO - аналоговый выход
\section pgIOC_secAskFile Конфигурационные ask-файлы
Формат файла имеет следующий вид:
\section pgIOC_secAskFile Конфигурационные ask-файлы
Формат файла имеет следующий вид:
\code
<IOConf readonly="1" dumptime="Wed Mar 23 14:14:42 2005">
<SensorsList>
<sensor name="MyProject/Sensors/AnalogSensor1_AS" node="" iotype="AI"
cmin="0" cmax="100" rmin="0" rmax="4096" default="50">
<sensor name="MyProject/Sensors/AnalogSensor1_AS" node="" iotype="AI" cmin="0" cmax="100" rmin="0" rmax="4096" default="50">
<consumer name="MyProject/ControlProcesses/Proc1" node=""/>
<consumer name="MyProject/ControlProcesses/Proc2" node=""/>
<consumer name="MyProject/ControlProcesses/Proc3" node=""/>
</sensor>
<sensor name="MyProject/Sensors/AnalogSensor2_AS" node="" iotype="AI"
cmin="10" cmax="500" rmin="0" rmax="4096" priority="">
<sensor name="MyProject/Sensors/AnalogSensor2_AS" node="" iotype="AI" cmin="10" cmax="500" rmin="0" rmax="4096" priority="">
<consumer name="MyProject/ControlProcesses/Proc1" node=""/>
<consumer name="MyProject/ControlProcesses/Proc2" node=""/>
<consumer name="MyProject/ControlProcesses/Proc3" node=""/>
......@@ -57,14 +53,11 @@
</SensorsList>
<ThresholdSensorList>
<sensor name="MyProject/Sensors/AnalogSensor1_AS" node="" iotype="AI">
<Threshold name="t1" lowlimit="5" hilimit="7" sensibility="0" id="0">
<consumer name="MyProject/ControlProcesses/Proc4" node=""/>
</Threshold>
<Threshold name="t2" lowlimit="90" hilimit="92" sensibility="0" id="1"
sid="MyProject/Sensors/ThreshooldSensor_FS" inverse="1"
/>
<Threshold name="t2" lowlimit="90" hilimit="92" sensibility="0" id="1" sid="MyProject/Sensors/ThreshooldSensor_FS" inverse="1"/>
</sensor>
<sensor name="MyProject/Sensors/AnalogSensor2_AS" node="" iotype="AI">
<Threshold name="t1" lowlimit="5" hilimit="7" sensibility="0" id="0" />
......@@ -74,128 +67,123 @@
</ThresholdSensorList>
</IOConf>
\endcode
Данный файл состоит из двух основных частей:
- \a SensorsList - список входов/выходов
- \a ThresholdSensorList - список пороговых датчиков формируемых из аналоговых значений.
Данный файл состоит из двух основных частей:
- \a SensorsList - список входов/выходов
- \a ThresholdSensorList - список пороговых датчиков формируемых из аналоговых значений.
В верхней части имеются два общих поля:
- \a readonly - признак того, что данный файл предназначен только для чтения
(запрет на автоматическое обновление)
- \a dumptime - время последней модификации
В верхней части имеются два общих поля:
- \a readonly - признак того, что данный файл предназначен только для чтения (запрет на автоматическое обновление)
- \a dumptime - время последней модификации
\sa \ref pgIOC_secAutoGen
\sa \ref pgIOC_secAutoGen
\subsection pgIOC_secDIO Дискретные датчики
\subsection pgIOC_secDIO Дискретные датчики
\code
<sensor name="MyProject/Sensors/DigitalSensor_S" node="" iotype="DI"
default="1" priotiry
anyparam...>
<sensor name="MyProject/Sensors/DigitalSensor_S" node="" iotype="DI" default="1" priotiry=".." anyparam...>
...
</sensor>
</sensor>
\endcode
Минимально необходимыми являются следующие поля:
- \a name - полное текстовое название идентификатора датчика в системе
- \a node - название узла. Если не задано, то считается Localhost.
- \a iotype - Тип входа/выхода.( см. \ref pgIOC_secIOTypes )
Минимально необходимыми являются следующие поля:
- \a name - полное текстовое название идентификатора датчика в системе
- \a node - название узла. Если не задано, то считается Localhost.
- \a iotype - Тип входа/выхода.( см. \ref pgIOC_secIOTypes )
Следующие поля необязательны:
- \a default - [1|0] значение по умолчанию. Т.е. значение на момент начального запуска.
По умолчанию имеет значение "0".
- \a priority - Приоритет посылаемого уведомления (UniSetTypes::SensorMessage) об изменении
данного датчика. По умолчанию имеет значение "Medium".
Следующие поля необязательны:
- \a default - [1|0] значение по умолчанию. Т.е. значение на момент начального запуска. По умолчанию имеет значение "0".
- \a priority - Приоритет посылаемого уведомления (UniSetTypes::SensorMessage) об изменении данного датчика. По умолчанию имеет значение "Medium".
Так же можно прописывать свои особенные параметры необходимые для специфичной настройки
каждого входа/выхода (например номер канала на плате в/в) и т.п.
каждого входа/выхода (например номер канала на плате в/в) и т.п.
\subsection pgIOC_secAIO Аналоговые датчики
\subsection pgIOC_secAIO Аналоговые датчики
В отличие от дискретных датчиков запись по аналоговому входу имеет вид:
\code
<sensor name="MyProject/Sensors/AnalogSensor_S" node="" iotype="AI"
<sensor name="MyProject/Sensors/AnalogSensor_S" node="" iotype="AI"
cmin="0" cmax="100" rmin="0" rmax="4096" default="50"
anyparam...>
...
</sensor>
</sensor>
\endcode
Минимально необходимыми являются следующие поля:
- \a name - полное текстовое название идентификатора датчика в системе
- \a node - название узла. Если не задано, то считается Localhost.
- \a iotype - Тип входа/выхода.( см. \ref pgIOC_secIOTypes )
- \a cmin - Минимальное калиброванное значение
- \a cmax - Максимальное калиброванное значение
- \a rmin - Минимальное "cырое" значение. ("сырое" - т.е. непосредственно получаемое)
- \a rmax - Максимальное "сырое" значение
Следующие поля необязательны:
- \a default - значение по умолчанию. Т.е. значение на момент начального запуска.
Минимально необходимыми являются следующие поля:
- \a name - полное текстовое название идентификатора датчика в системе
- \a node - название узла. Если не задано, то считается Localhost.
- \a iotype - Тип входа/выхода.( см. \ref pgIOC_secIOTypes )
- \a cmin - Минимальное калиброванное значение
- \a cmax - Максимальное калиброванное значение
- \a rmin - Минимальное "cырое" значение. ("сырое" - т.е. непосредственно получаемое)
- \a rmax - Максимальное "сырое" значение
Следующие поля необязательны:
- \a default - значение по умолчанию. Т.е. значение на момент начального запуска.
По умолчанию имеет значение "0".
- \a priority - Приоритет посылаемого уведомления (UniSetTypes::SensorMessage) об изменении
данного датчика. По умолчанию имеет значение "Medium".
- \a priority - Приоритет посылаемого уведомления (UniSetTypes::SensorMessage) об изменении
данного датчика. По умолчанию имеет значение "Medium".
\subsection pgIOC_secThresholds Пороговые датчики
\subsection pgIOC_secThresholds Пороговые датчики
Если какому-либо процессу требуется узнать о том, что значение аналогового датчика
достигло определённого порога. То для таких случае предназначены пороговые датчики.
Каждый аналоговый датчик может иметь любое (разумное) число порогов.
Формат записи выглядит следующим образом:
достигло определённого порога. То для таких случае предназначены пороговые датчики.
Каждый аналоговый датчик может иметь любое (разумное) число порогов.
Формат записи выглядит следующим образом:
\code
<sensor name="MyProject/Sensors/AnalogSensor1_AS" node="" iotype="AI">
<sensor name="MyProject/Sensors/AnalogSensor1_AS" node="" iotype="AI">
<Threshold name="t1" lowlimit="5" hilimit="7" sensibility="0" id="0">
<consumer name="MyProject/ControlProcesses/Proc4" node=""/>
</Threshold>
</sensor>
</sensor>
\endcode
В секции sensor прописываются только \a name, \a node, \a iotype аналогового датчика, из которого
формируются данные пороги. Причём датчик обязательно должен быть прописан в \a SensorsList.
\par
Поля для секции Threshold:
В секции sensor прописываются только \a name, \a node, \a iotype аналогового датчика, из которого
формируются данные пороги. Причём датчик обязательно должен быть прописан в \a SensorsList.
\par
Поля для секции Threshold:
- \a name - любое текстовое имя (пока никак не используется)
- \a lowlimit - нижний порог срабатывания. Как только аналоговое значение станет
- \a name - любое текстовое имя (пока никак не используется)
- \a lowlimit - нижний порог срабатывания. Как только аналоговое значение станет
<= (lowlimit-sensibility) посылается сообщение о срабатывании нижнего порога.
- \a hilimit - верхний порог срабатывания. Как только аналоговое значение станет
- \a hilimit - верхний порог срабатывания. Как только аналоговое значение станет
>= (hilimit+sensibility) посылается сообщение о срабатывании верхнего порога.
- \a sensibility - чувствительность. Значение, определяющее "мёртвую" зону. См. lowlimit, hilimit.
- \a sid - идентификатор дискретного (фиктивного) датчика. Позволяет связать данный порог
- \a sensibility - чувствительность. Значение, определяющее "мёртвую" зону. См. lowlimit, hilimit.
- \a sid - идентификатор дискретного (фиктивного) датчика. Позволяет связать данный порог
с фиктивным дискретным датчиком. Т.е. значение порога будет выставляться как
состояние датчика, указанного в поле "sid".
TRUE - при значении больше верхнего порога
FALSE - при значении меньше нижнего порога
- \a id - идентификатор порога(число). Значение которое используется для передачи
- \a id - идентификатор порога(число). Значение которое используется для передачи
в сообщении SensorMessage как идентификатор сработавшего порога. Должен
быть разный (уникальным) для разных порогов у одного аналогового датчика.
В случае использования "sid" id указывать необязательно.
- \a inverse - [1|0] позволяет инвертировать логику для датчика, указанного в поле sid.
- \a inverse - [1|0] позволяет инвертировать логику для датчика, указанного в поле sid.
В общем случае "пороги" не имеют отдельных уникальных идентификаторов. И каждый процесс
может заказать(сделать) себе любое количество "порогов" из одного аналогового датчика.
Но существует возможность связать дискретный датчик (в данном случае это будет фиктивный дискретный датчик)
с пороговым значением. Для этого прописывается следующая запись:
может заказать(сделать) себе любое количество "порогов" из одного аналогового датчика.
Но существует возможность связать дискретный датчик (в данном случае это будет фиктивный дискретный датчик)
с пороговым значением. Для этого прописывается следующая запись:
\code
<sensor name="MyProject/Sensors/AnalogSensor1_AS" node="" iotype="AI">
<sensor name="MyProject/Sensors/AnalogSensor1_AS" node="" iotype="AI">
<Threshold name="t2" lowlimit="90" hilimit="92" sensibility="0" id="1"
sid="MyProject/Sensors/ThreshooldSensor_FS" inverse="1"
/>
</sensor>
</sensor>
\endcode
В этом случае "порог" привязывается к датчику указанному в поле \a sid. При этом этот фиктивный
дискретный датчик должен быть прописан в \a SensorsList.
В этом случае "порог" привязывается к датчику указанному в поле \a sid. При этом этот фиктивный
дискретный датчик должен быть прописан в \a SensorsList.
\subsection pgIOC_secConsumers Заказчики
\subsection pgIOC_secConsumers Заказчики
"Заказчиком" является объект (процесс) которому будет присылаться уведомление
UniSetTypes::SensorMessage об изменении данного датчика. Заказывать уведомления
можно об изменении не только "входов", но и "выходов".
UniSetTypes::SensorMessage об изменении данного датчика. Заказывать уведомления
можно об изменении не только "входов", но и "выходов".
\section pgIOC_secSensorMessage Формат уведомления об изменении состояния (значения)
\section pgIOC_secSensorMessage Формат уведомления об изменении состояния (значения)
Для уведомления используется сообщение UniSetTypes::SensorMessage.
- \a state - текущее значение для дискретного датчика
- \a value - текущее значения для аналогового датчика
- \a state - текущее значение для дискретного датчика
- \a value - текущее значения для аналогового датчика
Для пороговых датчиков используются
- \a tid - идентификатор сработавшего порога
- \a threshold - текущее значение порога
Для пороговых датчиков используются
- \a tid - идентификатор сработавшего порога
- \a threshold - текущее значение порога
Остальные поля понятны из названия...
Остальные поля понятны из названия...
\section pgIOC_secAutoGen Автоматическое генерирование ask-файла
\section pgIOC_secAutoGen Автоматическое генерирование ask-файла
*/
\ No newline at end of file
/*!
\page MutexHowToPage Как пользоваться uniset_mutex и uniset_mutex_lock
\page MutexHowToPage Как пользоваться uniset_mutex и uniset_mutex_lock
\par
"мьютекс"(mutex) - получено от англ. Mutual Exclusive. (нечто вроде "взаимоисключение")
\par
"мьютекс"(mutex) - получено от англ. Mutual Exclusive. (нечто вроде "взаимоисключение")
\par
Основными операциями для мьютексов, помимо создания и уничтожения, являются операции lock и unlock.
Логически работа с мьютексом могла бы выглядеть так (псевдокод)
Основными операциями для мьютексов, помимо создания и уничтожения, являются операции lock и unlock.
Логически работа с мьютексом могла бы выглядеть так (псевдокод)
\code
\code
Mutex mutex;
...
mutex.lock();
DoSomething();
mutex.unlock();
\endcode
\endcode
Но в общем случае это ни к чему хорошему не приведет, т.к. если в \c DoSomething() возникнет исключение, то
\c mutex.unlock() уже не выполнится. Конечно можно использовать \c try...catch, но желательно, чтобы
код работал независимо от ситуации. Для этого введен класс \b uniset_mutex_lock. При его использовании получается
следующий код (один из вариантов использования):
\code
using namespase UniSetTypes;
...
uniset_mutex mutex;
...
{
Но в общем случае это ни к чему хорошему не приведет, т.к. если в \c DoSomething() возникнет исключение, то
\c mutex.unlock() уже не выполнится. Конечно можно использовать \c try...catch, но желательно, чтобы
код работал независимо от ситуации. Для этого введен класс \b uniset_mutex_lock. При его использовании получается
следующий код (один из вариантов использования):
\code
using namespase UniSetTypes;
...
uniset_mutex mutex;
...
{
uniset_mutex_lock lock(mutex); // вызов mutex.lock() как часть кода конструктора
DoSomething();
} // <-- Заканчивается зона видимости lock-а и происходит вызов mutex.unlock() как часть кода деструктора
\endcode
В этом случае, даже если в \c DoSomethig() будет сгенерировано исключение ресурс будет освобожден
при вызове деструктора. Вот и все решение...
\par
} // <-- Заканчивается зона видимости lock-а и происходит вызов mutex.unlock() как часть кода деструктора
\endcode
В этом случае, даже если в \c DoSomethig() будет сгенерировано исключение ресурс будет освобожден
при вызове деструктора. Вот и все решение...
\par
Главное не забывайте ставить скобочки...
\par
Желательно не использовать \c mutex.lock() и \c uniset_mutex.unlock() в чистом виде, а только совместно с
\b uniset_mutex_lock. Кроме особых случаев (см. \ref secWarning).
\par
Следует помнить, что мьютексы \b фактически никаких ресурсов не захватывают, это только флаг означающий,
что ресурс занят. Поэтому работать с ними надо внимательно и не забывать блокировать ресурс там где это надо.
\par
\par
Желательно не использовать \c mutex.lock() и \c uniset_mutex.unlock() в чистом виде, а только совместно с
\b uniset_mutex_lock. Кроме особых случаев (см. \ref secWarning).
\par
Следует помнить, что мьютексы \b фактически никаких ресурсов не захватывают, это только флаг означающий,
что ресурс занят. Поэтому работать с ними надо внимательно и не забывать блокировать ресурс там где это надо.
\par
Описания классов см. UniSetTypes::uniset_mutex и UniSetTypes::uniset_mutex_lock
\section secWarning Особые случаи
Если в \c DoSomethig() будет вызвана \c exit(0), \c abort() или что-нибудь подобное,
то unlock не произойдет. В таком случае следовало бы напрямую вызывать \c unlock() до вызова сигнала, но эти случаи редкие и если
возникнет необходимость, то можно будет вместо \a protected сделать их \a public.
\section secWarning Особые случаи
Если в \c DoSomethig() будет вызвана \c exit(0), \c abort() или что-нибудь подобное,
то unlock не произойдет. В таком случае следовало бы напрямую вызывать \c unlock() до вызова сигнала, но эти случаи редкие и если
возникнет необходимость, то можно будет вместо \a protected сделать их \a public.
\note Описание составлено на основе описания мьютексов из книги А.Цимбала "Технология CORBA для профессионалов".
\note Описание составлено на основе описания мьютексов из книги А.Цимбала "Технология CORBA для профессионалов".
*/
\ No newline at end of file
/* OBSOLETE DOC!!!
\page IONotifyControllerPage Как писать IONotifyController (процесс ввода/вывода)
\page IONotifyControllerPage Как писать IONotifyController (процесс ввода/вывода)
- \ref pgIONC_secDeclareIDL
- \ref pgIONC_secImplementation
- \ref pgIONC_secMain
- \ref pgIONC_secLT_Object
- \ref pgIONC_secRecomendation
- \ref pgIONC_secDeclareIDL
- \ref pgIONC_secImplementation
- \ref pgIONC_secMain
- \ref pgIONC_secLT_Object
- \ref pgIONC_secRecomendation
Все i/o процессы должны наследоваться от класса IOController. Если вам необходимо написать i/o процесс, который
помимо операций i/o еще и уведомляет об изменении состояния входов(выходов), то наследуйтесь от класса IONotifyController.
Эти классы объявляют минимальный(базовый) интерфейс для IOController-ов, который вы можете расширять.
Все i/o процессы должны наследоваться от класса IOController. Если вам необходимо написать i/o процесс, который
помимо операций i/o еще и уведомляет об изменении состояния входов(выходов), то наследуйтесь от класса IONotifyController.
Эти классы объявляют минимальный(базовый) интерфейс для IOController-ов, который вы можете расширять.
\par
Рассмотрим написание на примере простого процесса ввода/вывода, позволяющего заказывать у себя уведомления, а
так же обладающего дополнительной функцией CardIOTypes getCardIOType();
\par
Рассмотрим написание на примере простого процесса ввода/вывода, позволяющего заказывать у себя уведомления, а
так же обладающего дополнительной функцией CardIOTypes getCardIOType();
\section pgIONC_secDeclareIDL Объявление интерфейса на IDL
\section pgIONC_secDeclareIDL Объявление интерфейса на IDL
\note Написание интерфейса на IDL требуется, только если вам необходимо расширить базовый набор
IDL-функций. Все функции объявленные здесь станут доступны внешним объекта (локальным и удалённым).
......@@ -47,7 +47,7 @@
На основе этих файлов вы реализуете свой интерфейс на С++.
\section pgIONC_secImplementation Реализация интерфейса на C++
\section pgIONC_secImplementation Реализация интерфейса на C++
Необходимо создать класс реализующий объявленый интерфейс. Формирование названия класса и правила наследования
см. \ref UniSetLibStylePage.
\par
......@@ -148,19 +148,19 @@
\par
В завершение реализация запуска
\section pgIONC_secMain Написание функции main() для подключения процесса
\section pgIONC_secMain Написание функции main() для подключения процесса
\code
#include "ObjectsMap.h"
#include "MyNotifyController.h"
#include "ObjectsActivator.h"
#include "Configuration.h"
// ------------------------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
int main( int argc, char **argv )
{
#include "ObjectsMap.h"
#include "MyNotifyController.h"
#include "ObjectsActivator.h"
#include "Configuration.h"
// ------------------------------------------------------------------------------------------
using namespace UniSetTypes;
using namespace std;
int main( int argc, char **argv )
{
conf = new Configuration(argc, (const char**)argv, "configure.xml", (ObjectInfo*)ObjectsMap);
MyNotifyController nc( idMyNotifyController ); // idMyNotifyController - уникальный идентификатор объекта
......@@ -174,8 +174,8 @@
catch(...)
{
}
}
\endcode
}
\endcode
\section pgIONC_secLT_Object Создание автономного процесса, не зависящего от TimerService-а
......@@ -206,11 +206,11 @@
\endcode
Функция IONotifyController_LT::askTimer() повторяет интерфейс UniversalInterface::askTimer().
Реализация построена, на переопределении функции UniSetObject::callback(), поэтому если поток
не будет создан, таймеры работать не будут.
\sa LT_Object
не будет создан, таймеры работать не будут.
\sa LT_Object
\section pgIONC_secRecomendation Некоторые общие рекомендации
\section pgIONC_secRecomendation Некоторые общие рекомендации
-# Все функции и параметры должны быть откоментированы.
-# Заказ датчиков, таймеров, работа с информацией в основном происходит при помощи UniversalInterface. В каждом
......@@ -218,9 +218,9 @@
-# Не регистрируйте датчики в конструкторе.
-# Не вызывайте разрегистрацию в деструкторе.
\par
\par
Вот вроде и все пока...
\sa \ref ControlProcessPage
\sa \ref ControlProcessPage
*/
\ No newline at end of file
/* OBSOLETE DOC!!!
\page ObjectRepositoryPage Репозиторий объектов
\page ObjectRepositoryPage Репозиторий объектов
Репозиторий объектов предназначен для хранения и получения ссылок на объекты, с целью дальнейшего
использования функций предоставленных этими объектами. Объекты регистрирующиеся в репозитории могут быть удаленными...
использования функций предоставленных этими объектами. Объекты регистрирующиеся в репозитории могут быть удаленными...
- \ref subRegCommon
- \ref subReg
- \ref subResolve
- \ref subRegCommon
- \ref subReg
- \ref subResolve
\section subRegCommon Вводная
\section subRegCommon Вводная
При наследовании от UniSetObject (и его потомков) регистрация в репозитории происходит автоматически.
Поэтому регистрироваться отдельно нет необходимости.
Поэтому регистрироваться отдельно нет необходимости.
\section subReg Регистрация
\section subReg Регистрация
Для регистрации существует следующие функции.
По текстовому имени
......@@ -72,7 +72,7 @@
\endcode
\section subResolve Получение ссылки на объект
\section subResolve Получение ссылки на объект
Для получения ссылки лучше всего пользоваться
- UniSetTypes::ObjectPtr UniversalInterface::resolve( UniSetTypes::ObjectId id )
......
......@@ -11,22 +11,22 @@
- \ref OMAP_subDynamic_Example
\section OMAP_secCommon Общее описание карты объектов
\section OMAP_secCommon Общее описание карты объектов
Карта объектов задает идентификаторы объектов, узлов сети и координаты их размещения в репозитории.
Идентификатор объекта должен быть уникальным в пределах одного узла.
Идентификаторы являются неотрицательными числами, что \a минимизирует и \a упрощает передачу по
сетям различного типа (ethernet, CAN, profibus и т.п.). Хотя в использовании конечно удобнее
применять текстовые строки.
В данной реализации возможно использовать два способа задания карты объектов
- Статический на основе статического массива и enum-а.
- Динамический на основе xml-файла
В данной реализации возможно использовать два способа задания карты объектов
- Статический на основе статического массива и enum-а.
- Динамический на основе xml-файла
\section OMAP_secStatic Статическая карта объектов
\section OMAP_secStatic Статическая карта объектов
\subsection OMAP_subStatic_Create Создание карты
\subsection OMAP_subStatic_Create Создание карты
Статическую карту проще всего создать на основе препроцессора.
\par ObjectsMap.h
\par ObjectsMap.h
Заголовочный файл формируется при помощи препроцессора на основе файла ObjectsMapSource.h.
\code
......@@ -71,7 +71,7 @@ extern const UniSetTypes::ObjectInfo ObjectsMap[MAX_NUMOBJECTS];
\endcode
\par ObjectsMap.cc
\par ObjectsMap.cc
cc-файл формируемый при помощи препроцессора из файла ObjectsMapSource.h.
\code
......@@ -91,76 +91,76 @@ extern const UniSetTypes::ObjectInfo ObjectsMap[MAX_NUMOBJECTS];
//-----------------------------------------------------------------------------------------------------------------
const UniSetTypes::ObjectInfo ObjectsMap[MAX_NUMOBJECTS] =
{
\#include "ObjectsMapSource.h"
{0,0,0}
\#include "ObjectsMapSource.h"
{0,0,0}
};
\endcode
\par ObjectsMapSource.h
Это собственно карта объектов, в которой прописываются все объекты имеющие уникальные идентификаторы.
Это собственно карта объектов, в которой прописываются все объекты имеющие уникальные идентификаторы.
\code
// Sensors
// идентификатор, "Текстовое имя"
SET_SENSOR(minPressureOilD1_016N400_S, "Датчик давления1"),
SET_SENSOR(minPressureOilD1_013N400_S, "Датчик давления2"),
SET_SENSOR(minPressureOilD1_038N750_S, "Датчик давления3"),
SET_SENSOR(minPressureOilD1_034N750_S, "Датчик давления4"),
SET_SENSOR(maxTemperatureOilD1_S, "Датчик максимальной температуры"),
SET_SENSOR(maxDropPressureOilF1_S, "Датчик сброса давления"),
SET_SENSOR(levelUpOilPZ_S, "Верхний уровень давления масла"),
SET_SENSOR(levelDownOilPZ_S, "Нижний уровень давления масла"),
SET_SENSOR(levelUpOilMZ2_S, "Ля-ля-ля"),
SET_SENSOR(levelUpOilOZ_S, "Ля-ля-ля2"),
// AnalogSensors
SET_SENSOR(pressureOilD1_AS, "Датчик давления5"),
SET_SENSOR(temperatureOilD1_AS, "Датчик температуры"),
SET_SENSOR(dropPressureOilF1_AS, "Сброс давления"),
// Objects
SET_OBJECT(guiSystem),
SET_OBJECT(testControlProcess),
SET_OBJECT(testControlProcess2),
SET_OBJECT(tst1),
SET_OBJECT(tst2),
SET_OBJECT(mynthon),
// Controllers
SET_CONTROLLER(ioNotifyController1),
SET_CONTROLLER(ioNotifyController2),
// Services
SET_SERVICE(TimerService1),
SET_SERVICE(DBServer1),
// Nodes (alias, realname)
SET_NODENAME(ServerNode,ServerNode),
SET_NODENAME(Client1Node,Client1Node),
SET_NODENAME(Client2Node,Client2Node),
SET_NODENAME(Client3Node,Client3Node),
// Sensors
// идентификатор, "Текстовое имя"
SET_SENSOR(minPressureOilD1_016N400_S, "Датчик давления1"),
SET_SENSOR(minPressureOilD1_013N400_S, "Датчик давления2"),
SET_SENSOR(minPressureOilD1_038N750_S, "Датчик давления3"),
SET_SENSOR(minPressureOilD1_034N750_S, "Датчик давления4"),
SET_SENSOR(maxTemperatureOilD1_S, "Датчик максимальной температуры"),
SET_SENSOR(maxDropPressureOilF1_S, "Датчик сброса давления"),
SET_SENSOR(levelUpOilPZ_S, "Верхний уровень давления масла"),
SET_SENSOR(levelDownOilPZ_S, "Нижний уровень давления масла"),
SET_SENSOR(levelUpOilMZ2_S, "Ля-ля-ля"),
SET_SENSOR(levelUpOilOZ_S, "Ля-ля-ля2"),
// AnalogSensors
SET_SENSOR(pressureOilD1_AS, "Датчик давления5"),
SET_SENSOR(temperatureOilD1_AS, "Датчик температуры"),
SET_SENSOR(dropPressureOilF1_AS, "Сброс давления"),
// Objects
SET_OBJECT(guiSystem),
SET_OBJECT(testControlProcess),
SET_OBJECT(testControlProcess2),
SET_OBJECT(tst1),
SET_OBJECT(tst2),
SET_OBJECT(mynthon),
// Controllers
SET_CONTROLLER(ioNotifyController1),
SET_CONTROLLER(ioNotifyController2),
// Services
SET_SERVICE(TimerService1),
SET_SERVICE(DBServer1),
// Nodes (alias, realname)
SET_NODENAME(ServerNode,ServerNode),
SET_NODENAME(Client1Node,Client1Node),
SET_NODENAME(Client2Node,Client2Node),
SET_NODENAME(Client3Node,Client3Node),
//------------------------------------------------------------------------------
\endcode
\par Узлы
\par Узлы
Узлы задаются двумя параметрами: \a имя \a в \a программе и \a имя \a реальной \a ссылки. Для получения реального имени
необходимо пользоваться conf->getRealNodeName(nodeid).
необходимо пользоваться conf->getRealNodeName(nodeid).
\subsection OMAP_subStatic_Node Настройка узлов сети
\subsection OMAP_subStatic_Node Настройка узлов сети
Для того чтобы задать узлы сети помимо идентификатора необходимо внести информацию о них в настройки CORB-ы("omniORB.cfg").
Если узел доступен по нескольким сетям, то узлы должны называться (NodeName1...NodeNameX). NodeName - должно совпадать с именем realname в ObjectMap.
В ObjectsMap вносится только имя NodeName1(основной сети), остальные вносятся \b только в конф. файл.
При этом в UniversalInterface::resolve() автоматически будет пытаться связаться с другими узлами используя
резервные каналы NodeName2...NodeNameX.
\par В итоге файл настроек (для omniORB v.3) должен выглядеть примерно следующим образом:
Если узел доступен по нескольким сетям, то узлы должны называться (NodeName1...NodeNameX). NodeName - должно совпадать с именем realname в ObjectMap.
В ObjectsMap вносится только имя NodeName1(основной сети), остальные вносятся \b только в конф. файл.
При этом в UniversalInterface::resolve() автоматически будет пытаться связаться с другими узлами используя
резервные каналы NodeName2...NodeNameX.
\par В итоге файл настроек (для omniORB v.3) должен выглядеть примерно следующим образом:
\code
\code
ORBInitialHost localhost
ORBInitialPort 2809
ORBInitRef NameService=corbaname::localhost
......@@ -178,28 +178,28 @@ const UniSetTypes::ObjectInfo ObjectsMap[MAX_NUMOBJECTS] =
ORBInitRef ServerNode3=corbaname::192.168.3.100
\endcode
\endcode
\note Определять ссылки на узлы можно также передавая в параметрах при запуске программы. Например так:
myprogram -ORBInitRef ServerNode=corbaname::server:OMNIPORT -ORBInitRef LocalhostNode=corbaname::localhost:OMNIPORT
-ORBInitRef Client3Node=corbaname::client3:OMNIPORT
\note Определять ссылки на узлы можно также передавая в параметрах при запуске программы. Например так:
myprogram -ORBInitRef ServerNode=corbaname::server:OMNIPORT -ORBInitRef LocalhostNode=corbaname::localhost:OMNIPORT
-ORBInitRef Client3Node=corbaname::client3:OMNIPORT
\subsection OMAP_subStatic_Example Пример использования статической карты объектов
Как было показано выше, у нас должен быть создан файл \a ObjectsMapSource.h и два файла
с командами для препроцессора \a ObjectsMap.h (содержащий enum идентификаторов всех объектов в системе)
и \a ObjectsMap.cc (содержащий массив. Этот файл необходимо компилировать).
\par
с командами для препроцессора \a ObjectsMap.h (содержащий enum идентификаторов всех объектов в системе)
и \a ObjectsMap.cc (содержащий массив. Этот файл необходимо компилировать).
\par
При использовании статического способа в функции \a main при создании Configure используйте
следующий способ:
следующий способ:
\code
\#include <Configure.h>
\#include <ObjectsActivator.h>
\#include "ObjectysMap.h"
\#include <Configure.h>
\#include <ObjectsActivator.h>
\#include "ObjectysMap.h"
using namespace UniSetTypes;
using namespace UniSetTypes;
int main( int argc, char **argv )
{
int main( int argc, char **argv )
{
try
{
// первым делом надо создать Configure и инициализировать
......@@ -226,38 +226,38 @@ const UniSetTypes::ObjectInfo ObjectsMap[MAX_NUMOBJECTS] =
unideb[Debug::CRIT] << "Неизвестное исключение!!!!"<< endl;
}
retunr 0;
}
}
\endcode
Для использования в программе код должен выглядеть примерно следующим образом:
\code
\#include "ObjectsMap.h"
\#include "ObjectsMap.h"
...
// посылка сообщения объекту testControlProcess
MyMessage msg;
UniSetTypes::TransportMessage tmsg(msg.transport_msg());
...
// посылка сообщения объекту testControlProcess
MyMessage msg;
UniSetTypes::TransportMessage tmsg(msg.transport_msg());
cout << " send to object " << conf->oind->getNameById(testControlProcess);
if( ui.send(testControlProcess, tmsg) )
cout << " send to object " << conf->oind->getNameById(testControlProcess);
if( ui.send(testControlProcess, tmsg) )
cout << " OK!!!\n";
else
else
cout << " FAILED!!!\n";
...
...
// заказ датчика
try
{
// заказ датчика
try
{
ui.askSensor(maxTemperatureOilD1_S,UniversalIO::UIONotify);
}
catch(UniSetTypes::Exception& ex)
{
}
catch(UniSetTypes::Exception& ex)
{
cerr << ex << endl;
}
}
\endcode
\section OMAP_secDynamicXML Динамическая карта объектов на основе XML-файла
\subsection OMAP_subDynamic_Create Создание динамической карты объектов
\subsection OMAP_subDynamic_Example Пример использования динамической карты объектов
\section OMAP_secDynamicXML Динамическая карта объектов на основе XML-файла
\subsection OMAP_subDynamic_Create Создание динамической карты объектов
\subsection OMAP_subDynamic_Example Пример использования динамической карты объектов
*/
\ No newline at end of file
// эти разделы сформируются автоматически из описаний сделанных в соответствующих h-файлах
/*!
\page ServicesPage Сервисы
- \ref secDBServer
\section secDBServer Сервер БД
\sa \ref page_DBServer_MySQL
*/
\ No newline at end of file
/*!
\page UniSetLibStylePage Некоторые соглашения о стиле написания
\page UniSetLibStylePage Некоторые соглашения о стиле написания
- \ref secName
- \ref secName
- \ref subNameClass
- \ref subNameVar
- \ref subNameFunc
- \ref subNameFile
- \ref subNameDefine
- \ref subNameConst
- \ref secFormat
- \ref secFormat
- \ref secNoteHeader
- \ref secNoteCpp
- \ref secIDL
......@@ -16,27 +16,27 @@
- \ref subImplName
- \ref subDerivedName
\section secName Названия
\note Для автоматического форматирования проектов рекомендуется использовать программу astyle.
\subsection subNameClass Названия Классов
Названия классов должны начинаться с большой буквы.
Если название состоит из нескольких слов, то каждое слово
начинается с большой буквы.
\par
Обратите внимание, что public рекомендуется записывать
с отступом перед ним.
\code
class MyNameClass
{
\section secName Названия
\subsection subNameClass Названия Классов
Названия классов должны начинаться с большой буквы.
Если название состоит из нескольких слов, то каждое слово начинается с большой буквы.
\par
Обратите внимание, что public рекомендуется записывать с отступом перед ним.
\code
class MyNameClass
{
public:
...
};
\endcode
};
\endcode
При записи конструктора инициализация членов класса должна записываться
так:
\code
class MyNameClass
{
\code
class MyNameClass
{
public:
MyNameClass():
x(5)
......@@ -44,21 +44,21 @@
}
private:
int x;
};
\endcode
};
\endcode
\subsection subNameVar Названия переменных
\subsection subNameVar Названия переменных
Названия переменных и членов класса должны начинаться строчными буквами.
Если название составное, то второе слово нужно
писать с большой буквы.
\par
Записывать переменные полностью маленькими буквами,
разделяя слова подчёркиваниями, запрещается.
\code
int myVariableName;
\endcode
\code
int myVariableName;
\endcode
\subsection subNameFunc Названия функций
\subsection subNameFunc Названия функций
Названия функций должны начинаться с маленькой буквы.
Первым должен идти глагол.
Если название составное, то второе слово нужно
......@@ -71,118 +71,123 @@
между словами допустимо только для тех классов, которые
наследуются от библиотек, использующих аналогичную нотацию
(например, gtk--)
\code
\code
void printFunction(void);
void debugInfo();
\endcode
\endcode
\subsection subNameFile Названия файлов
\subsection subNameFile Названия файлов
Названия файлов должны начинаться с большой буквы.
Если в файлах описывается \b class \c MyNameClass, то названия файлов
должны быть соответственно \c MyNameClass.h и \c MyNameClass.cc.
Что касается оформления см. \ref secNoteHeader и \ref secNoteCpp
\subsection subNameDefine Название макросов
\subsection subNameDefine Название макросов
Определения макросов пишутся ЗАГЛАВНЫМИ БУКВАМИ (Кроме спец. макросов \c NameHeaderFile_H_)
Описание макросов лучше производить в заголовочном файле
в начале (см. \ref secNoteHeader).
Использование макросов \b не \b рекомендуется.
\subsection subNameConst Название констант и enum'ов
\subsection subNameConst Название констант и enum'ов
Названия констант и enum'ов начинаются с большой буквы.
\code
const int MyConst;
enum MyEnum { One, Two, Three };
\endcode
\section secFormat Форматирование
\section secFormat Форматирование
Ширина текста программы не должна превышать 78 символов для
возможности отображения на всех терминалах и печати на принтере.
Отступы в программе должны формироваться исключительно
знаками табуляции.
\par
Каждый может выбирать в настройках того редактора, который
он использует, сколько пробелов (4 или 8) использовать
знак табуляции. Рекомендуется 4 знака.
В редакторе mcedit в меню Настройка->Разное должно быть
отключено "Симулировать неполную табуляцию".
\par
Ширина текста программы не должна превышать 78 символов для возможности отображения на всех терминалах и печати на принтере.
Отступы в программе должны формироваться исключительно знаками табуляции.
\par
Каждый может выбирать в настройках того редактора, который он использует, сколько пробелов (4 или 8) использовать
знак табуляции. Рекомендуется 4 знака. В редакторе mcedit в меню Настройка->Разное должно быть отключено
"Симулировать неполную табуляцию".
\par
Фигурные скобки во всех случаях записываются одна под другой.
\par
Условия. Скобки записываются через пробел после if.
Не используйте лишних скобок при записи || и &&
\par
Условия. Скобки записываются через пробел после if. Не используйте лишних скобок при записи || и &&
\code
function (void)
{
\code
function (void)
{
body of the function;
if (a > b || a < c)
if( a > b || a < c )
{
body of the condition;
}
else if (x > y)
else if( x > y )
{
body of the not condition;
}
}
\endcode
При длинных названиях переменных рекомендуется записывать
содержимое круглых скобок как в примере ниже
\code
if ( veryLongA > veryLongB )
}
\endcode
При длинных названиях переменных рекомендуется записывать
содержимое круглых скобок как в примере ниже
\code
if( veryLongA > veryLongB )
{
body of the condition;
}
\endcode
С короткими названиями лучше запись
\code
if (a>b)
\endcode
С короткими названиями лучше запись
\code
if( a > b )
{
...
}
\endcode
Присваивания записываются как
\code
\endcode
Присваивания записываются как
\code
veryLongA = veryLongB;
\endcode
для коротких переменных допустима запись
\code
\endcode
для коротких переменных допустима запись
\code
a=b;
\endcode
Типы данных. Знаки, относящиеся к типу, записываются слитно
с названием типа.
\code
\endcode
Типы данных. Знаки, относящиеся к типу, записываются слитно
с названием типа.
\code
PointerToObject* p;
ReferenceToObject& r;
\endcode
Часто используемые локальные переменные рекомендуется называть
короткими именами, такими как
\par
i,j для переменных цикла
\par
p для указателя
\par
it для итератора
\par
obj для объекта
\endcode
Часто используемые локальные переменные рекомендуется называть
короткими именами, такими как
\par
i,j для переменных цикла
\par
p для указателя
\par
it для итератора
\par
obj для объекта
\section secNoteHeader Оформление заголовочных файлов
Заголовочные файлы имеют расширение .h
Кроме приведенного в примере, конечно должны быть комментарии.
\section secNoteHeader Оформление заголовочных файлов
Заголовочные файлы имеют расширение .h
Кроме приведенного в примере, конечно должны быть комментарии.
\code
/***************************************************************************
* This file is part of the UniSet* library *
* Copyright (C) 2002 SET Research Institute. All rights reserved. *
***************************************************************************/
/*! \file
/*
* Copyright (c) xxxx Name Noname
*
* 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
* \brief Заголовочный файл для организации низкоуровневого ввода-вывода.
* \author Vitaly Lipatov <lav>
* \date $Date: 2005/12/03 11:13:10 $
* \version $Id: UniSetLibStyle.dox,v 1.2 2005/12/03 11:13:10 vpashka Exp $
* \par
* Этот файл предназначен для внутреннего использования в классах
* ввода-вывода
*/
* Этот файл предназначен для внутреннего использования в классах ввода-вывода
*/
/**************************************************************************/
#ifndef MyNameClass_H_
......@@ -197,7 +202,12 @@
// -----------------------------------------------------------------------
const float MyPI = 3.14;
enum MyEnum { En1, En2, En3 };
enum MyEnum
{
En1, // comment 1
En2, // comment 2
En3 // comment 3
};
// -----------------------------------------------------------------------
......@@ -219,89 +229,92 @@ class MyNameClass
\note Большая просьба ко всем разработчикам избегать глобальных
Enum-ов (как в примере), дабы избежать в последствии ошибок.
\section secNoteCpp Оформление cpp-файлов
\section secNoteCpp Оформление cpp-файлов
Кроме приведенного в примере, конечно должны быть комментарии.
\code
/***************************************************************************
* This file is part of the UniSet* library *
* Copyright (C) 2002 SET Research Institute. All rights reserved. *
***************************************************************************/
/*! \file
\code
/*
* Copyright (c) xxxx Name Noname
*
* 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
* \brief Это файл обеспечения
* \author Vitaly Lipatov <lav>
* \date $Date: 2005/12/03 11:13:10 $
* \version $Id: UniSetLibStyle.dox,v 1.2 2005/12/03 11:13:10 vpashka Exp $
* Некоторые комментарии к файлу
*
*/
*/
/**************************************************************************/
#include <std.h>
#include <...>
#include <std.h>
#include <...>
#include "MyNameClass.h"
#include "..."
// -----------------------------------------------------------------------------------------
#include "MyNameClass.h"
#include "..."
// -----------------------------------------------------------------------------------------
void MyNameClass::func1(void)
{
void MyNameClass::func1(void)
{
...
}
}
// -----------------------------------------------------------------------------------------
void MyNameClass::func2(void)
{
...
}
// -----------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------
void MyNameClass::func2(void)
{
...
// -----------------------------------------------------------------------------------------
\endcode
}
// -----------------------------------------------------------------------------------------
...
// -----------------------------------------------------------------------------------------
\endcode
\section secIDL Написание интерфейсов на языке IDL
\section secIDL Написание интерфейсов на языке IDL
\subsection subIDLCommit Общая часть
Названия интерфейсов(классов), функций и переменных см. \ref secName.
Оформление файла IDL аналогично оформлению заголовочных файлов.
(См. \ref secNoteHeader) Название интерфейса должно образовываться
от названия и добавления к нему "_i", что означает интерфейсный класс.
\subsection subImplName Имена классов реализаций
Название класса реализации должно образовываться от
названия интерфейса, исключив "_i".
Пример:
\par объявление на IDL
\code
\subsection subImplName Имена классов реализаций
Название класса реализации должно образовываться от названия интерфейса, исключив "_i".
Пример:
\par объявление на IDL
\code
interface BaseProcess_i
{
...
}
\endcode
\par объявление класса реализации
\code
\endcode
\par объявление класса реализации
\code
class BaseProcess:
public POA_BaseProcess_i,
public ...
{
...
}
\endcode
\endcode
\subsection subDerivedName Класс родитель для реализации
В общем случае классом родителем должен являться класс
POA_имя_интерфейса. Этот класс генерируется
автоматически и его описание находится в файле
имя_интерфейса.hh . В особо оговариваемых случаях
наследование может происходить от другого класса.
Не исключается множественное наследование
для добавления необходимых свойств и т.п. Вот пример
наследования для реализации idl-интерфейса ContolProcess_i:
\code
\subsection subDerivedName Класс родитель для реализации
В общем случае классом родителем должен являться класс POA_имя_интерфейса. Этот класс генерируется
автоматически и его описание находится в файле имя_интерфейса.hh . В особо оговариваемых случаях
наследование может происходить от другого класса.
Не исключается множественное наследование для добавления необходимых свойств и т.п.
Вот пример наследования для реализации idl-интерфейса ContolProcess_i:
\code
class ControlProcess:
public BaseProcess,
public POA_ControlProcess_i
{
...
}
\endcode
\endcode
*/
......@@ -45,10 +45,10 @@
\section secORep Функции работы с репозиторием объектов
- \ref void UniversalInterface::registered(...)
- \ref void UniversalInterface::unregister(...)
- \ref void UniversalInterface::resolve(...)
- \ref ObjectId UniversalInterface::getIdByName(...)
- \ref const char* UniversalInterface::getNameById(...)
- \ref void UniversalInterface::unregister(...)
- \ref void UniversalInterface::resolve(...)
- \ref ObjectId UniversalInterface::getIdByName(...)
- \ref const char* UniversalInterface::getNameById(...)
\section secTimers Заказ таймеров
- \ref void UniversalInterface::askTimer(...)
......
......@@ -3,17 +3,17 @@
- \ref secSection1
- \ref subIO
- Алгоритмы управления
- \ref UniSetGraphics
- \ref UniDiag
- Алгоритмы управления
- \ref UniSetGraphics
- \ref UniDiag
- \ref secSection2
- \ref subTransfer
- \ref subDBSave
- \ref subTransfer
- \ref subDBSave
- \ref secDetail
- \ref subObjects
- \ref subProcesses
- \ref subProcesses
- \ref secResourses
- \ref secDirStruct
......@@ -23,69 +23,69 @@
менеджеров сообщений и т.п.). Любую систему управления можно поделить на относительно независимые объекты решающие
следующие задачи:
- ввод/вывод (опрос физических датчиков, обмен с другими устройствами)
- алгоритмы управления тем или иным устройств или группой устройств
- отображение информации (графический интерфейс пользователя)
- накопление и хранение информации
- просмотр накопленной информации
\par
Для каждой из задач в библиотеке разработан определенный компонент(группа компонентов).
И разработаны универсальные механизмы взаимодействия объектов между собой.
- алгоритмы управления тем или иным устройств или группой устройств
- отображение информации (графический интерфейс пользователя)
- накопление и хранение информации
- просмотр накопленной информации
\par
Для каждой из задач в библиотеке разработан определенный компонент(группа компонентов).
И разработаны универсальные механизмы взаимодействия объектов между собой.
\section secSection2 Общие принципы работы
Библиотека позволяет объектам системы обмениваться сообщениями, а так же непосредственно вызывать функции друг-друга. В системе объектами
управляют менеджеры. Которые позволяют управлять (через этот) менеджер сразу набором подчиненных ему объектов. Менеджер может
содержать в себе в качестве подчиненного объекта другой менеджер, что позволяет строить довольно гибкую иерархическую структуру
управления. Всё взаимодействие объектов( сетевое и межпроцессовое) строится на базе CORBA-ы.
управляют менеджеры. Которые позволяют управлять (через этот) менеджер сразу набором подчиненных ему объектов. Менеджер может
содержать в себе в качестве подчиненного объекта другой менеджер, что позволяет строить довольно гибкую иерархическую структуру
управления. Всё взаимодействие объектов( сетевое и межпроцессовое) строится на базе CORBA-ы.
\subsection subTransfer Взаимодействие объектов системы
\subsection subTransfer Взаимодействие объектов системы
Взаимодействие объектов между собой происходит через ObjectRepository. Каждый объект становится доступным другим объектам только
после регистрации в репозитории. Для получения доступа к другому объекту (даже удаленному) необходимо знать его идентификатор(UniSetTypes::ObjectId)
и при помощи репозитория получить на него ссылку, с которой можно работать как с указателем на объект.
после регистрации в репозитории. Для получения доступа к другому объекту (даже удаленному) необходимо знать его идентификатор(UniSetTypes::ObjectId)
и при помощи репозитория получить на него ссылку, с которой можно работать как с указателем на объект.
...
Каждый узел по возможности должен работать с максимальной автономностью. Т.е. все основные сервисы (TimerService, InfoServer, DBServer)
должны быть запущены локально. Минимизирован объем данных передаваемых между узлами системы.
должны быть запущены локально. Минимизирован объем данных передаваемых между узлами системы.
\subsection subDBSave Система накопления информации
\subsection subDBSave Система накопления информации
Хранение накопленной информации реализовано на основе БД. Для этого предусмотрен специальный процесс(сервис)
называемый DBServer, обладающий специальным интерфейсом, скрывающим детали работы с конкретной БД. Основная идея состоит
в том, что данный сервис запускается на каждом узле и все процессы, которым необходимо сохранять в БД информацию работают,
с всегда доступным локальным DBServer-ом. В свою очередь этот локальный DBServer при необходимости пересылает всю
информацию на другие узлы, на которых производится реальная запись в БД. Помимо это локальный DBServer может обеспечивать
буферизацию данных на время недоступности других узлов.
называемый DBServer, обладающий специальным интерфейсом, скрывающим детали работы с конкретной БД. Основная идея состоит
в том, что данный сервис запускается на каждом узле и все процессы, которым необходимо сохранять в БД информацию работают,
с всегда доступным локальным DBServer-ом. В свою очередь этот локальный DBServer при необходимости пересылает всю
информацию на другие узлы, на которых производится реальная запись в БД. Помимо это локальный DBServer может обеспечивать
буферизацию данных на время недоступности других узлов.
\sa \ref secDBServer
\subsection subIO Ввод/вывод
\subsection subIO Ввод/вывод
Процессы ввода/вывода строятся на основе классов IOController и IONotifyController.
\par IOController
Это унифицированный интерфейс для сохранения и получения информации о состоянии дискретных и
аналоговых датчиков.
аналоговых датчиков.
\par IONotifyController
Расширение IOController-а. Предоставляющее интерфейс для заказа уведомлений об изменении состояния датчиков.
\subsection UniSetGraphics Графический интерфейс пользователя
\subsection UniSetGraphics Графический интерфейс пользователя
...
\subsection UniDiag Просмотр накопленной информации
\subsection UniDiag Просмотр накопленной информации
Для большей универсальности слежение за работой системы, диагностирование и просмотр накопленной информации
сделаны в виде web-интерфейса написанного на PHP. \a в \a процессе \a разработки...
сделаны в виде web-интерфейса написанного на PHP. \a в \a процессе \a разработки...
\section secDetail Подробности
\subsection subObjects Объекты, Менеджеры, Активаторы
\par Объекты (UniSetObject)
\subsection subObjects Объекты, Менеджеры, Активаторы
\par Объекты (UniSetObject)
Объекты являются пассивными единицами, так как не могут функционировать без менеджера или активатора. Для того, чтобы объект
мог принимать сообщения и предоставлять свои функции другим объектам он должен быть зарегистрирован в менеджере объектов
(ObjectsManager) или напрямую в активаторе (ObjectsActivator) при помощи функции ObjectsManager::addObject(...).
\par Менеджеры (ObjectsManager)
\par Менеджеры (ObjectsManager)
Менеджеры используются для управления сразу группой объектов, а также сами являются объектами и могут быть
зарегистрированы в другом менеджере (или активаторе). Они тоже являются пассивными единицами, так как не могут функционировать без
активатора.
\par Активаторы (ObjectsActivator)
\par Активаторы (ObjectsActivator)
Активатор предназначен для активизации объектов и менеджеров. Он обладает свойствами менеджера (позволяет регистрировать в себе
другие объекты и менеджеры) и свойствами объекта (может быть зарегистрирован в другом активаторе или менеджере). Обычно для
запуска достаточно одного активатора.
\subsection subProcesses Процессы и потоки
\subsection subProcesses Процессы и потоки
Для активизации объектов должен быть создан хотя-бы один активатор. После вызова функции ObjectsActivator::run( thread ) он
активизирует свои подчиненные объекты. В зависимости от заданного параметра функции ObjectsActivator::run()
он создает поток (thread=true) или захватывает ресурсы основного потока откуда вызван (thread=false) для передачи его
......@@ -106,18 +106,18 @@
в основном потоке программы. А также несколько потоков для orb.
\section secResourses Используемые библиотеки
- libmysqlclient, libtcpwrapGK - работа с MySQL
- linomniORB3(4) - реализация CORBA (удаленный доступ к объектам)
- libmysqlclient, libtcpwrapGK - работа с MySQL
- linomniORB3(4) - реализация CORBA (удаленный доступ к объектам)
\section secDirStruct Структура каталогов
- \b /conf - общие конфигурационные файлы библиотеки UniSet
- \b /Documents - документация к библиотеке
- \b /IDL - декларации написанные на IDL
- \b /include - h-файлы
- \b /lib - библиотека \c libUniSet.a
- \b /src - сс-файлы
- \b /Tests - отладочные и тестовые программы
- \b /Utilities - вспомогательные утилиты входящие в состав UniSet
- \b /conf - общие конфигурационные файлы библиотеки UniSet
- \b /Documents - документация к библиотеке
- \b /IDL - декларации написанные на IDL
- \b /include - h-файлы
- \b /lib - библиотека \c libUniSet.a
- \b /src - сс-файлы
- \b /Tests - отладочные и тестовые программы
- \b /Utilities - вспомогательные утилиты входящие в состав UniSet
*/
/*!
\page DependsPage Зависимости между датчиками
Существует два механизма реализующих зависимость между датчиками:
Существует два механизма реализующих зависимость между датчиками:
- \ref pgDep_secIOControl
- \ref pgDep_secIOBase
\section pgDep_secIOControl Зависимость на уровне IOController (SharedMemmory)
\section pgDep_secIOControl Зависимость на уровне IOController (SharedMemmory)
Механизм зависимостей реализован в классе IOController.
Механизм зависимостей реализован в классе IOController.
Пример записи "зависимости" в configure.xml:
Пример записи "зависимости" в configure.xml:
\code
<item textname="...." iotype="..." .../>
<item textname="...." iotype="..." .../>
<consumers>
<consumers>
<depends>
<depend name="Sensor1" filter="val" />
<depend name="Sensor2" filter2="val1" />
</depends>
</item>
</item>
\endcode
При считывании конф. файла можно задавать фильтры.
При считывании конф. файла можно задавать фильтры.
ПОКА РЕАЛИЗОВАНА ЗАВИСИМОСТЬ ТОЛЬКО ОТ ОДНОГО ДАТЧИКА!
т.е. <depend> может быть только один.
ПОКА РЕАЛИЗОВАНА ЗАВИСИМОСТЬ ТОЛЬКО ОТ ОДНОГО ДАТЧИКА!
т.е. <depend> может быть только один.
\section pgDep_secIOBase Зависимость на уровне IOBase
Механизм зависимостей между датчиками на уровне IOBase,
\section pgDep_secIOBase Зависимость на уровне IOBase
Механизм зависимостей между датчиками на уровне IOBase,
работает на уровне процессов обмена использующих IOBase.
В ним относятся IOControl, ModbusMaster (RTU,TCP) и т.п.
Плюсом данного механизма является, то, что он обеспечивает
......@@ -42,9 +42,9 @@
Следует иметь ввиду, что этот механизм не действует при сохранении значений, например при помощи uniset-admin,
в отличие от механизма \ref pgDep_secIOControl
Пример записи "зависимости" в configure.xml:
Пример записи "зависимости" в configure.xml:
\code
<item textname="...." iotype="..." ... depend="OtherSensor_AS" depend_value="2" />
<item textname="...." iotype="..." ... depend="OtherSensor_AS" depend_value="2" />
\endcode
В данном случае подразумевается, что разрешающим датчиком является OtherSensor_AS=2.
......
/*! \page page_Uniset Краткое описание библиотеки libuniset
- \ref pg_UniSet_Common
- \ref pg_Uniset_Processes
- \ref pg_UniSet_Network
- \ref pg_UniSet_Utilities
- \ref pg_UniSet_Common
- \ref pg_Uniset_Processes
- \ref pg_UniSet_Network
- \ref pg_UniSet_Utilities
\section pg_UniSet_Common Общее описание libuniset
......
/*!
\mainpage
\mainpage
\image html uniset.png
\image html uniset.png
\section MainSection Оглавление
\section MainSection Оглавление
- \ref page_Concept
- \ref page_Uniset
- \ref UniSetLibStylePage
- \ref page_Concept
- \ref page_Uniset
- \ref UniSetLibStylePage
*/
/*!
\page ToDoPage Необходимо доделать
\page ToDoPage Необходимо доделать
-# утилиты мониторинга работы системы
-# настройку "политик" для ORB сделать из конф. файла
-# по максимуму переход на xml
-# дополнить описание IOController-ов разделом про XML-файл заказчиков(создание,работа)
-# сделать описание принципов и деталей межобъектного взаимодействия
(об ограничениях на размер сообщений, очередь сообщений, приоритеты и т.п.)
-# попытаться сделать работу с сервисами более универсальной
(что то типа "UniSetTypes::ObjectId conf->getService(const string name)" )
-# откорректировать и дописать "общее описание" библиотеки
-# сделать тип в UniSetObject::getType string-ом
(для универсальности и простоты будущих расширений)
-# переписать тестовые примеры, под текущую ситуацию.
-# в будущем попытаться отказаться от ObjectId и перейти на строки (это надо ещё обдумать)
-# в InfoServer-е по routeList-у сообщения пересылаются, только если они локальные.
Надо переделать механизм, чтобы можно было отделять тех кому пересылать все сообщения,
от тех кому пересылать только локальные....
-# Для IOController-ов разработать спец. интерфейс для работы с датчиками (сохранение, получение состояния и т.п.)
-# утилиты мониторинга работы системы
-# настройку "политик" для ORB сделать из конф. файла
-# по максимуму переход на xml
-# дополнить описание IOController-ов разделом про XML-файл заказчиков(создание,работа)
-# сделать описание принципов и деталей межобъектного взаимодействия
(об ограничениях на размер сообщений, очередь сообщений, приоритеты и т.п.)
-# попытаться сделать работу с сервисами более универсальной
(что то типа "UniSetTypes::ObjectId conf->getService(const string name)" )
-# откорректировать и дописать "общее описание" библиотеки
-# сделать тип в UniSetObject::getType string-ом
(для универсальности и простоты будущих расширений)
-# переписать тестовые примеры, под текущую ситуацию.
-# в будущем попытаться отказаться от ObjectId и перейти на строки (это надо ещё обдумать)
-# в InfoServer-е по routeList-у сообщения пересылаются, только если они локальные.
Надо переделать механизм, чтобы можно было отделять тех кому пересылать все сообщения,
от тех кому пересылать только локальные....
-# Для IOController-ов разработать спец. интерфейс для работы с датчиками (сохранение, получение состояния и т.п.)
Для того, чтобы можно было использовать разные способы хранения (БД, STL-контейнеры, файлы и т.п.). Т.к. сейчас
жёсткая реализация на STL-контейнерах.
-# дописать Mutex как надо (или перейти на omni_mutex-ы) . Сделать RWMutex и RMutex.
-# стартовые скрипты для локальной отладки (откорректировать старые)
-# управление очередью сообщений, очистка по фильтру и т.п. (может перейти на несколько очередей по приоритетам)
-# У NotifyController-а две функции с название calibrate (надо переименовать)
-# Сделать свойство tick у процессов обмена по Modbus, чтобы можно было с разной периодичностью опрашивать разные регистры
жёсткая реализация на STL-контейнерах.
-# дописать Mutex как надо (или перейти на omni_mutex-ы) . Сделать RWMutex и RMutex.
-# стартовые скрипты для локальной отладки (откорректировать старые)
-# управление очередью сообщений, очистка по фильтру и т.п. (может перейти на несколько очередей по приоритетам)
-# У NotifyController-а две функции с название calibrate (надо переименовать)
-# Сделать свойство tick у процессов обмена по Modbus, чтобы можно было с разной периодичностью опрашивать разные регистры
*/
/*! \page page_Codegen Генератор кода uniset-codegen
- \ref pg_Codegen_Common
- \ref pg_Codegen_XmlFile
- \ref pg_Codegen_Settings
- \ref pg_Codegen_SMap
- \ref pg_Codegen_MsgMap
- \ref pg_Codegen_Variables
- \ref pg_Codegen_argprefix
- \ref pg_Codegen_Configuration
- \ref pg_Codegen_TestMode
- \ref pg_Codegen_Make
- \ref pg_Codegen_Templ_Ask
- \ref pg_Codegen_Templ_Alone
- \ref pg_Codegen_log
- \ref pg_Codegen_loglevel
- \ref pg_Codegen_logserver
- \ref pg_Codegen_vmonitor
- \ref pg_Codegen_Common
- \ref pg_Codegen_XmlFile
- \ref pg_Codegen_Settings
- \ref pg_Codegen_SMap
- \ref pg_Codegen_MsgMap
- \ref pg_Codegen_Variables
- \ref pg_Codegen_argprefix
- \ref pg_Codegen_Configuration
- \ref pg_Codegen_TestMode
- \ref pg_Codegen_Make
- \ref pg_Codegen_Templ_Ask
- \ref pg_Codegen_Templ_Alone
- \ref pg_Codegen_log
- \ref pg_Codegen_loglevel
- \ref pg_Codegen_logserver
- \ref pg_Codegen_vmonitor
\section pg_Codegen_Common Общее описание утилиты uniset-codegen
Утилита uniset-codegen предназначена для генерирования "скелета" процесса управления на основе
......@@ -62,12 +62,12 @@
\code
<?xml version="1.0" encoding="utf-8"?>
<!--
name - название класса
msgcount - сколько сообщений обрабатывается за один раз
sleep_msec - пауза между итерациями в работе процесса
name - название класса
msgcount - сколько сообщений обрабатывается за один раз
sleep_msec - пауза между итерациями в работе процесса
type
====
type
====
in - входные регистры (только для чтения)
out - выходные регистры (запись)
-->
......@@ -75,8 +75,8 @@
<settings>
<set name="class-name" val="TestGen"/>
<set name="msg-count" val="20"/>
<set name="sleep-msec" val="150"/>
<set name="logrotate" val="append"/>
<set name="sleep-msec" val="150"/>
<set name="logrotate" val="append"/>
</settings>
<variables>
<!-- type = [int,str,bool,float]
......@@ -97,11 +97,11 @@
<item name="test_str" type="str" default="ddd"/>
</variables>
<smap>
<!-- name - название переменной в конф. файле -->
<item name="input1_s" vartype="in" iotype="DI" comment="comment for input1"/>
<item name="input2_s" vartype="in" iotype="DI" comment="comment for input2" />
<item name="output1_c" vartype="out" iotype="DO" omment="comment for output1" no_check_id="1"/>
<item name="output2_c" vartype="out" iotype="DO" omment="comment for output2" force="1"/>
<!-- name - название переменной в конф. файле -->
<item name="input1_s" vartype="in" iotype="DI" comment="comment for input1"/>
<item name="input2_s" vartype="in" iotype="DI" comment="comment for input2" />
<item name="output1_c" vartype="out" iotype="DO" omment="comment for output1" no_check_id="1"/>
<item name="output2_c" vartype="out" iotype="DO" omment="comment for output2" force="1"/>
</smap>
<msgmap>
......@@ -143,8 +143,8 @@
\a --argprefix-resetMsgTime \a msec, либо задать в файле описания в секции \b <settings>
\code
<settings>
...
<set name="resetMsgTime" val="500"/>
...
<set name="resetMsgTime" val="500"/>
</settings>
\endcode
Для сообщений генерируется такой же набор "переменных" как и для полей указанных в \<smap> (см. \ref pg_Codegen_SMap). За исключением того,
......@@ -182,7 +182,7 @@
\code
varname = conf->getArgParam("--'arg_prefix'varname'",it.getProp("'varname'"));
if( varname.empty() )
varname = 'default'
varname = 'default'
\endcode
Где \a it.getProp() - получение значения из соответствующей настроечной секции в конфигурационном файле (см. \ref pg_Codegen_Configuration).
Из кода можно видеть, что приоритетным является аргумент командной строки, потом значение из конф. файла и только потом \a default.
......@@ -233,18 +233,18 @@
(обычно в секции \<settings>) создаётся настроечная секция для вашего объекта.
А в самом классе генерируется специальный конструктор, позволяющий указать настроечный xml-узел:
\code
ClassName( UniSetTypes::ObjectId id, xmlNode* node=UniSetTypes::conf->getNode("ClassName") );
ClassName( UniSetTypes::ObjectId id, xmlNode* node=UniSetTypes::conf->getNode("ClassName") );
\endcode
Ниже приведён пример настроечной секции, для объекта сгенерированного на основе xml-файла указанного в \ref pg_Codegen_XmlFile
\code
...
<TestGen name="TestGen" startTimeout="4000" stopTimeout="2000"
...
<TestGen name="TestGen" startTimeout="4000" stopTimeout="2000"
input1_s="Input1_S" node_input1_s="Node2"
input2_s="DumpSensor1_S"
output1_c="DO_C"
msg1="Message1"
/>
...
/>
...
\endcode
Обычно для каждого объекта класса создаётся своя настроечная секция.
......@@ -258,7 +258,7 @@
\section pg_Codegen_TestMode Специальный режим "тест" (TestMode)
В генератор кода заложен специальный код для перевода процесса в тестовый режим. В этом режиме отключается вся работа процесса.
В генератор кода заложен специальный код для перевода процесса в тестовый режим. В этом режиме отключается вся работа процесса.
Перестают обрабатываться сообщения, обновляться входы и выходы и т.д.
Для перевода процесса в "тестовый режим" необходимо задать идентификаторы для двух "DI" датчиков:
......@@ -307,12 +307,12 @@
...
<settings>
...
<TestGenAlone name="TestGenAlone">
<TestGenAlone name="TestGenAlone">
<set name="ID" val="TestGenAlone"/>
<set name="class-name" val="TestGenAlone"/>
<set name="msg-count" val="20"/>
<set name="sleep-msec" val="150"/>
</TestGenAlone>
</TestGenAlone>
...
</settings>
...
......@@ -353,7 +353,7 @@
..._SOURCES= MyClass_SK.cc ...
MyClass_SK.cc: myclass.src.xml
@UNISET_CODEGEN@ -n MyClass --no-main myclass.src.xml
@UNISET_CODEGEN@ -n MyClass --no-main myclass.src.xml
\endcode
В этом примере
......@@ -372,8 +372,8 @@ MyClass_SK.cc: myclass.src.xml
Так же можно использовать функции напрямую:
\code
mylog->info() << "....test..." << endl;
mylog->log1() << "....test..." << endl;
mylog->info() << "....test..." << endl;
mylog->log1() << "....test..." << endl;
\endcode
\p Помимо объекта mylog класс содержит ряд вспомогательных функций:
......@@ -381,9 +381,9 @@ MyClass_SK.cc: myclass.src.xml
- \b string \b dumpIO() - вывод состояния всех входов и выходов в строку, в виде:
\code
ObjectName:
in_input1_s(Sensor1_S)=1
in_output2_c(Output1_C)=0
...
in_input1_s(Sensor1_S)=1
in_output2_c(Output1_C)=0
...
\endcode
- \b string \b str(ObjectId,showLinkName) - вывод названия указанного входа или выхода в формате "in_input1_s(Sensor1_S)". Если
......@@ -408,16 +408,16 @@ MyClass_SK.cc: myclass.src.xml
loglevel="1". Пример:
\code
<smap>
...
<item name="loglevel_s" vartype="in" comment="log level control" loglevel="1"/>
...
<item name="loglevel_s" vartype="in" comment="log level control" loglevel="1"/>
</smap>
\endcode
Данный механизм позволяет посредством этого датчика управлять уровнем вывода логов (mylog) во время работы процесса.
Для удобства предусмотрена утилита \b uniset2-log2val позволяющая преобразовать текстовые названия уровней в число,
которое необходимо выставить датчику. Пример:
\code
uniset2-log2val info,level1,warn,level9
4117
uniset2-log2val info,level1,warn,level9
4117
\endcode
Т.е. для того, чтобы включить указанные логи в датчик нужно записать число \b 4117
......@@ -437,25 +437,25 @@ MyClass_SK.cc: myclass.src.xml
Непосредственно управление логами производиться при помощи утилиты \b uniset2-log
\code
-h, --help - this message
-v, --verbose - Print all messages to stdout
[-i|--iaddr] addr - LogServer ip or hostname.
[-p|--port] port - LogServer port.
[-c|--command-only] - Send command and break. (No read logs).
[-w|--timeout] msec - Timeout for wait data. Default: 0 - endless waiting
[-x|--reconnect-delay] msec - Pause for repeat connect to LogServer. Default: 5000 msec.
Commands:
[--add | -a] info,warn,crit,... [logfilter] - Add log levels.
[--del | -d] info,warn,crit,... [logfilter] - Delete log levels.
[--set | -s] info,warn,crit,... [logfilter] - Set log levels.
--off, -o [logfilter] - Off the write log file (if enabled).
--on, -e [logfilter] - On(enable) the write log file (if before disabled).
--rotate, -r [logfilter] - rotate log file.
--list, -l [logfilter] - List of managed logs.
--filter, -f logfilter - ('filter mode'). View log only from 'logfilter'(regexp)
Note: 'logfilter' - regexp for name of log. Default: ALL logs.
-h, --help - this message
-v, --verbose - Print all messages to stdout
[-i|--iaddr] addr - LogServer ip or hostname.
[-p|--port] port - LogServer port.
[-c|--command-only] - Send command and break. (No read logs).
[-w|--timeout] msec - Timeout for wait data. Default: 0 - endless waiting
[-x|--reconnect-delay] msec - Pause for repeat connect to LogServer. Default: 5000 msec.
Commands:
[--add | -a] info,warn,crit,... [logfilter] - Add log levels.
[--del | -d] info,warn,crit,... [logfilter] - Delete log levels.
[--set | -s] info,warn,crit,... [logfilter] - Set log levels.
--off, -o [logfilter] - Off the write log file (if enabled).
--on, -e [logfilter] - On(enable) the write log file (if before disabled).
--rotate, -r [logfilter] - rotate log file.
--list, -l [logfilter] - List of managed logs.
--filter, -f logfilter - ('filter mode'). View log only from 'logfilter'(regexp)
Note: 'logfilter' - regexp for name of log. Default: ALL logs.
\endcode
\section pg_Codegen_vmonitor Мониторинг состояния внутренних переменных
......
......@@ -66,6 +66,7 @@ void BackendOpenTSDB::init( xmlNode* cnode )
bufSyncTime = conf->getArgPInt("--" + prefix + "-buf-sync-time", it.getProp("bufSyncTimeout"), bufSyncTime);
int sz = conf->getArgPInt("--" + prefix + "-uniset-object-size-message-queue", it.getProp("sizeOfMessageQueue"), 10000);
if( sz > 0 )
setMaxSizeOfMessageQueue(sz);
......@@ -347,6 +348,7 @@ bool BackendOpenTSDB::flushBuffer()
if( ret < 0 )
{
int errnum = errno;
if( errnum == EPIPE || errnum == EBADF )
{
mywarn << "(flushBuffer): send error (" << errnum << "): " << strerror(errnum) << endl;
......@@ -369,6 +371,7 @@ bool BackendOpenTSDB::flushBuffer()
{
mywarn << "(flushBuffer): (io): " << ex.displayText() << endl;
lastError = ex.displayText();
if( !reconnect() )
askTimer(tmReconnect, reconnectTime);
}
......
......@@ -31,7 +31,7 @@ namespace uniset
{
// -----------------------------------------------------------------------------
/*!
\page page_BackendOpenTSDB Реализация шлюза к БД поддерживающей интерфейс OpenTSDB
\page page_BackendOpenTSDB (DBServer_OpenTSDB) Реализация шлюза к БД поддерживающей интерфейс OpenTSDB
- \ref sec_OpenTSDB_Comm
- \ref sec_OpenTSDB_Conf
......@@ -98,6 +98,8 @@ namespace uniset
\todo Нужна ли поддержка авторизации для TSDB (возможно придётся перейти на HTTP REST API)
\todo Доделать возможность задать политику при переполнении буфера (удалять последние или первые, сколько чистить)
*/
// -----------------------------------------------------------------------------
/*! Реализация DBServer для OpenTSDB */
class BackendOpenTSDB:
public UObject_SK
{
......
......@@ -53,7 +53,7 @@ namespace uniset
\par
Для повышения надежности DBServer периодически ( DBServer_MySQL::PingTimer ) проверяет наличие связи с сервером БД.
В случае если связь пропала (или не была установлена при старте) DBServer пытается вновь каждые DBServer::ReconnectTimer
произвести соединение. При этом все запросы которые поступают для записи в БД, но не могут быть записаны складываются
произвести соединение.При этом все запросы которые поступают для записи в БД, но не могут быть записаны складываются
в буфер (см. \ref sec_DBS_Buffer).
\warning При каждой попытке восстановить соединение DBServer заново читает конф. файл. Поэтому он может подхватить
новые настройки.
......@@ -147,6 +147,8 @@ namespace uniset
\warning Временно, для обратной совместимости поле 'time_usec' в таблицах оставлено с таким названием,
хотя фактически туда сейчас сохраняется значение в наносекундах!
*/
//------------------------------------------------------------------------------------------
/*! Реализация DBServer для MySQL */
class DBServer_MySQL:
public DBServer
{
......
......@@ -60,12 +60,12 @@ bool PostgreSQLInterface::ping() const
}
catch( const std::exception& e )
{
// lastE = string(e.what());
// lastE = string(e.what());
}
return false;
// return db && db->is_open();
// return db && db->is_open();
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::reconnect(const string& host, const string& user, const string& pswd, const string& dbname, unsigned int port )
......@@ -73,7 +73,7 @@ bool PostgreSQLInterface::reconnect(const string& host, const string& user, cons
if( db )
close();
return nconnect(host,user,pswd, dbname, port);
return nconnect(host, user, pswd, dbname, port);
}
// -----------------------------------------------------------------------------------------
bool PostgreSQLInterface::nconnect(const string& host, const string& user, const string& pswd, const string& dbname, unsigned int port )
......@@ -254,7 +254,7 @@ void PostgreSQLInterface::save_inserted_id( const pqxx::result& res )
bool PostgreSQLInterface::isConnection() const
{
return db && ping();
// return (db && db->is_open())
// return (db && db->is_open())
}
// -----------------------------------------------------------------------------------------
DBResult PostgreSQLInterface::makeResult( const pqxx::result& res )
......
......@@ -71,6 +71,7 @@ void DBServer_SQLite::sysCommand( const uniset::SystemMessage* sm )
case SystemMessage::Finish:
{
activate = false;
if(db)
db->close();
}
......@@ -79,6 +80,7 @@ void DBServer_SQLite::sysCommand( const uniset::SystemMessage* sm )
case SystemMessage::FoldUp:
{
activate = false;
if(db)
db->close();
}
......
......@@ -53,7 +53,7 @@ namespace uniset
\par
Для повышения надежности DBServer периодически ( DBServer_SQLite::PingTimer ) проверяет наличие связи с сервером БД.
В случае если связь пропала (или не была установлена при старте) DBServer пытается вновь каждые DBServer::ReconnectTimer
произвести соединение. При этом все запросы которые поступают для записи в БД, но не могут быть записаны складываются
произвести соединение.При этом все запросы которые поступают для записи в БД, но не могут быть записаны складываются
в буфер (см. \ref sec_DBS_Buffer).
\warning При каждой попытке восстановить соединение DBServer заново читает конф. файл. Поэтому он может подхватить
новые настройки.
......@@ -147,6 +147,8 @@ namespace uniset
\warning Временно, для обратной совместимости поле 'time_usec' в таблицах оставлено с таким названием,
хотя фактически туда сейчас сохраняется значение в наносекундах!
*/
//------------------------------------------------------------------------------------------
/*! Реализация DBServer для SQLite */
class DBServer_SQLite:
public DBServer
{
......
......@@ -1517,7 +1517,7 @@ namespace uniset
check_testmode();
}
for( auto && it : iomap )
for( auto&& it : iomap )
{
if( it->si.id == sm->id )
{
......
......@@ -60,109 +60,106 @@ namespace uniset
в качестве префикса по умолчанию используется "io", но в конструкторе можно задать другой
если используется несколько процессов ввода/вывода.
<br>\b --io-confnode name - Использовать для настройки указанный xml-узел
<br>\b --io-name name - ID процесса. По умолчанию IOController1.
<br>\b --io-numcards - Количество карт в/в. По умолчанию 1.
<br>\b --iodev0 dev - Использовать для card='0' указанный файл comedi-устройства.
<br>\b --iodev1 dev - Использовать для card='1' указанный файл comedi-устройства.
<br>\b --iodev2 dev - Использовать для card='2' указанный файл comedi-устройства.
<br>\b --iodev3 dev - Использовать для card='3' указанный файл comedi-устройства.
<br>\b --iodevX dev - Использовать для card='X' указанный файл comedi-устройства.
- \b --io-confnode name - Использовать для настройки указанный xml-узел
- \b --io-name name - ID процесса. По умолчанию IOController1.
- \b --io-numcards - Количество карт в/в. По умолчанию 1.
- \b --iodev0 dev - Использовать для card='0' указанный файл comedi-устройства.
- \b --iodev1 dev - Использовать для card='1' указанный файл comedi-устройства.
- \b --iodev2 dev - Использовать для card='2' указанный файл comedi-устройства.
- \b --iodev3 dev - Использовать для card='3' указанный файл comedi-устройства.
- \b --iodevX dev - Использовать для card='X' указанный файл comedi-устройства.
'X' не должен быть больше --io-numcards
<br>\b --iodevX-subdevX-type name - Настройка типа подустройства для UNIO.
- \b --iodevX-subdevX-type name - Настройка типа подустройства для UNIO.
Разрешены: TBI0_24,TBI24_0,TBI16_8
<br>\b --io-default_cardnum - Номер карты по умолчанию. По умолчанию -1.
- \b --io-default_cardnum - Номер карты по умолчанию. По умолчанию -1.
Если задать, то он будет использоваться для датчиков
у которых не задано поле 'card'.
<br>\b --io-test-lamp - Для данного узла в качестве датчика кнопки 'ТестЛамп' использовать указанный датчик.
<br>\b --io-conf-field fname - Считывать из конф. файла все датчики с полем fname='1'
<br>\b --io-polltime msec - Пауза между опросом карт. По умолчанию 200 мсек.
<br>\b --io-filtersize val - Размерность фильтра для аналоговых входов.
<br>\b --io-filterT val - Постоянная времени фильтра.
<br>\b --io-s-filter-field - Идентификатор в configure.xml по которому считывается список относящихся к это процессу датчиков
<br>\b --io-s-filter-value - Значение идентификатора по которому считывается список относящихся к это процессу датчиков
<br>\b --io-blink-time msec - Частота мигания, мсек. По умолчанию в configure.xml
<br>\b --io-blink2-time msec - Вторая частота мигания (lmpBLINK2), мсек. По умолчанию в configure.xml
<br>\b --io-blink3-time msec - Вторая частота мигания (lmpBLINK3), мсек. По умолчанию в configure.xml
<br>\b --io-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-датчиком.
<br>\b --io-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10.
<br>\b --io-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')
<br>\b --io-force - Сохранять значения в SM, независимо от, того менялось ли значение
<br>\b --io-force-out - Обновлять выходы принудительно (не по заказу)
<br>\b --io-skip-init-output - Не инициализировать 'выходы' при старте
<br>\b --io-sm-ready-test-sid - Использовать указанный датчик, для проверки готовности SharedMemory
- \b --io-test-lamp - Для данного узла в качестве датчика кнопки 'ТестЛамп' использовать указанный датчик.
- \b --io-conf-field fname - Считывать из конф. файла все датчики с полем fname='1'
- \b --io-polltime msec - Пауза между опросом карт. По умолчанию 200 мсек.
- \b --io-filtersize val - Размерность фильтра для аналоговых входов.
- \b --io-filterT val - Постоянная времени фильтра.
- \b --io-s-filter-field - Идентификатор в configure.xml по которому считывается список относящихся к это процессу датчиков
- \b --io-s-filter-value - Значение идентификатора по которому считывается список относящихся к это процессу датчиков
- \b --io-blink-time msec - Частота мигания, мсек. По умолчанию в configure.xml
- \b --io-blink2-time msec - Вторая частота мигания (lmpBLINK2), мсек. По умолчанию в configure.xml
- \b --io-blink3-time msec - Вторая частота мигания (lmpBLINK3), мсек. По умолчанию в configure.xml
- \b --io-heartbeat-id - Данный процесс связан с указанным аналоговым heartbeat-датчиком.
- \b --io-heartbeat-max - Максимальное значение heartbeat-счётчика для данного процесса. По умолчанию 10.
- \b --io-ready-timeout - Время ожидания готовности SM к работе, мсек. (-1 - ждать 'вечно')
- \b --io-force - Сохранять значения в SM, независимо от, того менялось ли значение
- \b --io-force-out - Обновлять выходы принудительно (не по заказу)
- \b --io-skip-init-output - Не инициализировать 'выходы' при старте
- \b --io-sm-ready-test-sid - Использовать указанный датчик, для проверки готовности SharedMemory
\par Возможные настройки по каждому входу/выходу
<br>\b nofilter - не использовать фильтр
<br>\b ioignore - игнорировать данный датчик (позволяет временно отключить вход/выход)
<br>\b ioinvert - инвертированная логика (для DI,DO)
<br>\b default - значение по умолчанию (при запуске)
<br>\b noprecision - игнорировать поле precision (т.е. процесс в/в не будет его использовать,
но будет его присылать в SensorMessage)
<br>\b cal_nocrop - не обрезать значение по крайним точкам по при калибровке.
- \b nofilter - не использовать фильтр
- \b ioignore - игнорировать данный датчик (позволяет временно отключить вход/выход)
- \b ioinvert - инвертированная логика (для DI,DO)
- \b default - значение по умолчанию (при запуске)
- \b noprecision - игнорировать поле precision (т.е. процесс в/в не будет его использовать, но будет его присылать в SensorMessage)
- \b cal_nocrop - не обрезать значение по крайним точкам по при калибровке.
<br>\b breaklim - пороговое значение для определения обрыва датчика (используется для AI).
- \b breaklim - пороговое значение для определения обрыва датчика (используется для AI).
Если значение ниже этого порога, то выставляется признак обрыва датчика.
<br>\b debouncedelay - защита от дребезга. Задержка на дребезг, мсек.
<br>\b ondelay - задержка на срабатывание, мсек.
<br>\b offdelay - задержка на отпускание, мсек.
<br>\b iofront - работа по фронту сигнала (для DI).
<br> "01" - срабатывание (и отпускание) по переходу "0 --> 1"
<br> "10" - срабатывание (и отпускание) по переходу "1 --> 0"
<br>\b safety - безопасное значение. Значение которое сохраняется в случае аварийного
завершения процесса.
<br>\b iopriority - приоритет при опросе.
<br>\b iotype - тип входа/выхода [DI|DO|AI|AO]
<br>\b rmin - минимальное "сырое" значение
<br>\b rmax - максимальное "сырое" значение
<br>\b cmin - минимальное "калиброванное" значение
<br>\b cmax - максимальное "калиброванное" значение
<br>\b precision - Точность. Задаёт количество знаков после запятой.
<br>Т.е. при считывании из канала, значение домножается
<br>на 10^precision и уже таким сохраняется.
<br>А в SensorMessage присылается присылается precision.
<br>\b filtermedian - Значение для "медианного" фильтра
<br>\b filtersize - Значение для "усреднения"
<br>\b filterT - Постоянная времени фильтра.
<br>\b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>.
<br>\b cal_cachesize - Размер кэша в калибровочной диаграмме (Calibration.h)
<br>\b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной пересортировки. (Calibration.h)
<br>\b threshold_aid - идентификатор аналогового датчика по которому формируется порог.
- \b debouncedelay - защита от дребезга. Задержка на дребезг, мсек.
- \b ondelay - задержка на срабатывание, мсек.
- \b offdelay - задержка на отпускание, мсек.
- \b iofront - работа по фронту сигнала (для DI).
- "01" - срабатывание (и отпускание) по переходу "0 --> 1"
- "10" - срабатывание (и отпускание) по переходу "1 --> 0"
- \b safety - безопасное значение. Значение которое сохраняется в случае аварийного завершения процесса.
- \b iopriority - приоритет при опросе.
- \b iotype - тип входа/выхода [DI|DO|AI|AO]
- \b rmin - минимальное "сырое" значение
- \b rmax - максимальное "сырое" значение
- \b cmin - минимальное "калиброванное" значение
- \b cmax - максимальное "калиброванное" значение
- \b precision - Точность. Задаёт количество знаков после запятой.
- Т.е. при считывании из канала, значение домножается
- на 10^precision и уже таким сохраняется.
- А в SensorMessage присылается присылается precision.
- \b filtermedian - Значение для "медианного" фильтра
- \b filtersize - Значение для "усреднения"
- \b filterT - Постоянная времени фильтра.
- \b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>.
- \b cal_cachesize - Размер кэша в калибровочной диаграмме (Calibration.h)
- \b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной пересортировки. (Calibration.h)
- \b threshold_aid - идентификатор аналогового датчика по которому формируется порог.
Используется для DI.
<br>\b lowlimit - нижний порог срабатывания.
<br>\b hilimit - верхний порог срабатывания.
<br>\b card - номер карты
<br>\b subdev - номер подустройства
<br>\b channel [ 0<>32 ] - номер канала
<br>\b jack [ J1 | J2 | J3 | J4 | J5 ] - название разъёма. Можно задавать вместо channel
<br>&nbsp;&nbsp; J1 - chanenel 0 - 15
<br>&nbsp;&nbsp; J2
<br>\b lamp - признак, что данный аналоговый датчик является "лампочкой".
<br> Т.е. на самом деле дискретный выход, который может иметь состояния:
<br>uniset::lmpOFF - выключен
<br>uniset::lmpON - включен
<br>uniset::lmpBLINK - мигание с частотой 1
<br>uniset::lmpBLINK2 - мигание с частотой 2
<br>uniset::lmpBLINK3 - мигание с частотой 3
<br>\b no_iotestlamp - игнорировать данную лампочку при тесте ламп.
<br>\b range - диапазон измерения аналогового входа (см. libcomedi)
<br>\b aref - тип подключения (см. libcomedi)
<br>\b enable_testmode - включить в работу во время тестового режима tmConfigEnable
<br>\b disable_testmode - исключить из работы в тестовом режиме tmConfigDisable.
- \b lowlimit - нижний порог срабатывания.
- \b hilimit - верхний порог срабатывания.
- \b card - номер карты
- \b subdev - номер подустройства
- \b channel [ 0<>32 ] - номер канала
- \b jack [ J1 | J2 | J3 | J4 | J5 ] - название разъёма. Можно задавать вместо channel
- &nbsp;&nbsp; J1 - chanenel 0 - 15
- &nbsp;&nbsp; J2
- \b lamp - признак, что данный аналоговый датчик является "лампочкой".
- Т.е. на самом деле дискретный выход, который может иметь состояния:
- uniset::lmpOFF - выключен
- uniset::lmpON - включен
- uniset::lmpBLINK - мигание с частотой 1
- uniset::lmpBLINK2 - мигание с частотой 2
- uniset::lmpBLINK3 - мигание с частотой 3
- \b no_iotestlamp - игнорировать данную лампочку при тесте ламп.
- \b range - диапазон измерения аналогового входа (см. libcomedi)
- \b aref - тип подключения (см. libcomedi)
- \b enable_testmode - включить в работу во время тестового режима tmConfigEnable
- \b disable_testmode - исключить из работы в тестовом режиме tmConfigDisable.
\note Помимо этого для конкретного процесса можно переопределять настройки используя "prefix_" (префикс плюс подчёркивание).
Где "prefix" - это префикс это префикс заданный в конструкторе IOControl.
......@@ -176,14 +173,14 @@ namespace uniset
--io-test-mode ID либо в конфигурационном файле testmode_as="ID"
Сейчас поддерживаются следующий режимы (см. IOControl::TestModeID):
<br>\b "0" - тестовый режим отключён. Обычная работа.
<br>\b "1" - полностью отключить работу с картами в/в. При этом все выходы будут переведены в безопасное состояние.
<br>\b "2" - Режим "разрешённых" каналов. В этом режиме отключается работа со всеми каналами, кроме тех, у которых
- \b "0" - тестовый режим отключён. Обычная работа.
- \b "1" - полностью отключить работу с картами в/в. При этом все выходы будут переведены в безопасное состояние.
- \b "2" - Режим "разрешённых" каналов. В этом режиме отключается работа со всеми каналами, кроме тех, у которых
указан параметр enable_testmode="1".
<br>\b "3" - Режим "запрещённых" каналов. В этом режиме отключается работа ТОЛЬКО для каналов, у которых
- \b "3" - Режим "запрещённых" каналов. В этом режиме отключается работа ТОЛЬКО для каналов, у которых
указан параметр disable_testmode="1".
<br>\b "4" - Режим "только входы"
<br>\b "5" - Режим "только выходы"
- \b "4" - Режим "только входы"
- \b "5" - Режим "только выходы"
*/
// -----------------------------------------------------------------------------
/*! \todo (IOControl): Сделать обработку сигналов завершения */
......@@ -261,7 +258,7 @@ namespace uniset
IOInfo( IOInfo&& r ) = default;
IOInfo& operator=(IOInfo&& r) = default;
IOInfo(){}
IOInfo() {}
int subdev = { DefaultSubdev }; /*!< (UNIO) подустройство (см. comedi_test для конкретной карты в/в) */
int channel = { DefaultChannel }; /*!< (UNIO) канал [0...23] */
......
......@@ -191,6 +191,7 @@ LogDB::LogDB( const string& name, int argc, const char* const* argv, const strin
l->signal_on_read().connect(sigc::mem_fun(this, &LogDB::addLog));
auto lfile = sit.getProp("logfile");
if( !lfile.empty() )
{
l->logfile = make_shared<DebugStream>();
......
......@@ -78,11 +78,8 @@ namespace uniset
\endcode
При этом доступно два способа:
* Первый - это использование секции в общем файле проекта (configure.xml).
* Второй способ - позволяет создать отдельный xml-файл с одной настроечной секцией и указать его
в аргументах командной строки
* Второй способ - позволяет создать отдельный xml-файл с одной настроечной секцией и указать его в аргументах командной строки
\code
uniset2-logdb --single-confile logdbconf.xml
\endcode
......@@ -175,6 +172,8 @@ namespace uniset
\todo Продумать и реализовать тесты
\todo rest: Добавить функцию получения значений внутренних переменных и настроек (для отладки LogDB)
*/
//------------------------------------------------------------------------------------------
/*! Реализация LogDB */
class LogDB:
public EventLoopServer
#ifndef DISABLE_REST_API
......@@ -231,7 +230,7 @@ namespace uniset
static std::string qLast( const std::string& p );
// преобразование в дату 'YYYY-MM-DD' из строки 'YYYYMMDD' или 'YYYY/MM/DD'
static std::string qDate(const std::string& p , const char sep = '-');
static std::string qDate(const std::string& p, const char sep = '-');
// экранирование кавычек (удваивание для sqlite)
static std::string qEscapeString( const std::string& s );
......@@ -261,7 +260,7 @@ namespace uniset
ev::sig sigTERM;
ev::sig sigQUIT;
ev::sig sigINT;
void onTerminate( ev::sig& evsig , int revents );
void onTerminate( ev::sig& evsig, int revents );
ev::async wsactivate; // активация LogWebSocket-ов
......
......@@ -81,7 +81,7 @@ namespace uniset
{
long _myout = getOut();
for( auto && it : outs )
for( auto&& it : outs )
it.el->setIn(it.num, _myout);
}
// -------------------------------------------------------------------------
......@@ -105,7 +105,7 @@ namespace uniset
// -------------------------------------------------------------------------
void Element::addInput(size_t num, long value )
{
for( auto && it : ins )
for( auto&& it : ins )
{
if( it.num == num )
{
......
......@@ -173,7 +173,7 @@ void LProcessor::build( const string& lfile )
*/
void LProcessor::getInputs()
{
for( auto && it : extInputs )
for( auto&& it : extInputs )
{
// try
// {
......
......@@ -117,7 +117,7 @@ void PassiveLProcessor::askSensors( UniversalIO::UIOCommand cmd )
{
try
{
for( auto && it : extInputs )
for( auto&& it : extInputs )
shm->askSensor(it.sid, cmd);
}
catch( const uniset::Exception& ex )
......@@ -129,7 +129,7 @@ void PassiveLProcessor::askSensors( UniversalIO::UIOCommand cmd )
// -------------------------------------------------------------------------
void PassiveLProcessor::sensorInfo( const uniset::SensorMessage* sm )
{
for( auto && it : extInputs )
for( auto&& it : extInputs )
{
if( it.sid == sm->id )
it.value = sm->value;
......@@ -250,7 +250,7 @@ void PassiveLProcessor::initIterators()
void PassiveLProcessor::setOuts()
{
// выcтавляем выходы
for( auto && it : extOuts )
for( auto&& it : extOuts )
{
try
{
......
......@@ -97,7 +97,7 @@ namespace uniset
e1->delChildOut(e2);
// удаляем из списка соединений
for( auto && lit = inLinks.begin(); lit != inLinks.end(); ++lit )
for( auto&& lit = inLinks.begin(); lit != inLinks.end(); ++lit )
{
if( lit->from == e1 && lit->to == e2 )
{
......@@ -140,7 +140,7 @@ namespace uniset
// -------------------------------------------------------------------------
void Schema::remove( std::shared_ptr<Element>& el )
{
for( auto && it = emap.begin(); it != emap.end(); ++it )
for( auto&& it = emap.begin(); it != emap.end(); ++it )
{
if( it->second == el )
{
......@@ -150,7 +150,7 @@ namespace uniset
}
// помечаем внутренние связи
for( auto && lit : inLinks )
for( auto&& lit : inLinks )
{
if( lit.from == el )
lit.from = 0;
......@@ -160,7 +160,7 @@ namespace uniset
}
// помечаем внешние связи
for( auto && lit : extLinks )
for( auto&& lit : extLinks )
{
if( lit.to == el )
lit.to = 0;
......
......@@ -24,7 +24,7 @@ namespace uniset
using namespace std;
using namespace uniset::extensions;
// -------------------------------------------------------------------------
TA2D::TA2D(Element::ElementID id , long filterValue ):
TA2D::TA2D(Element::ElementID id, long filterValue ):
Element(id),
myout(false),
fvalue(filterValue)
......
......@@ -36,7 +36,7 @@ namespace uniset
void TAND::setIn( size_t num, long value )
{
// cout << this << ": input " << num << " set " << state << endl;
for( auto && it : ins )
for( auto&& it : ins )
{
if( it.num == num )
{
......@@ -53,7 +53,7 @@ namespace uniset
// проверяем изменился ли выход
// для тригера 'AND' проверка до первого 0
for( auto && it : ins )
for( auto&& it : ins )
{
if( !it.value )
{
......
......@@ -50,7 +50,7 @@ namespace uniset
{
// cout << getType() << "(" << myid << "): input " << num << " set " << state << endl;
for( auto && it : ins )
for( auto&& it : ins )
{
if( it.num == num )
{
......@@ -67,7 +67,7 @@ namespace uniset
// проверяем изменился ли выход
// для тригера 'OR' проверка до первой единицы
for( auto && it : ins )
for( auto&& it : ins )
{
if( it.value )
{
......
......@@ -354,9 +354,9 @@ bool MQTTPublisher::RangeInfo::check( long val ) const
return ( val >= rmin && val <= rmax );
}
//--------------------------------------------------------------------------------
void MQTTPublisher::MQTTTextInfo::check( mosqpp::mosquittopp* serv, long value , std::shared_ptr<DebugStream>& log , const string& myname )
void MQTTPublisher::MQTTTextInfo::check( mosqpp::mosquittopp* serv, long value, std::shared_ptr<DebugStream>& log, const string& myname )
{
for( auto && r : rlist )
for( auto&& r : rlist )
{
if( r.check(value) )
{
......
......@@ -84,6 +84,7 @@ namespace uniset
<msg value="14" text="My text for value %v"/>
<range min="10" max="20" text="My text for range %r. %n = %v"/>
<mqtt>
...
</item>
\endcode
- \b range - задаёт диапазон включающий [min,max]
......@@ -103,6 +104,8 @@ namespace uniset
\note Если заданные "одиночные" значения совпадают с диапазоном, то будет сгенерировано несколько сообщений. Т.е. диапазоны могут пересекаться.
*/
// -----------------------------------------------------------------------------
/*! Реализация публикатора на основе MQTT */
class MQTTPublisher:
protected mosqpp::mosquittopp,
public UObject_SK
......
......@@ -420,7 +420,7 @@ namespace uniset
shm->initIterator(d->resp_it);
shm->initIterator(d->mode_it);
for( auto && m : d->pollmap )
for( auto&& m : d->pollmap )
{
auto& regmap = m.second;
......@@ -448,7 +448,7 @@ namespace uniset
{
auto d = it1->second;
for( auto && m : d->pollmap )
for( auto&& m : d->pollmap )
{
auto regmap = m.second;
......@@ -1265,7 +1265,7 @@ namespace uniset
}
}
for( auto && m : d->pollmap )
for( auto&& m : d->pollmap )
{
auto& regmap = m.second;
......@@ -1324,7 +1324,7 @@ namespace uniset
{
auto& r = rit->second;
for( auto && it : r->slst )
for( auto&& it : r->slst )
updateRSProperty( &it, false );
}
......@@ -2274,7 +2274,7 @@ namespace uniset
// ------------------------------------------------------------------------------------------
MBExchange::RSProperty* MBExchange::addProp( PList& plist, RSProperty&& p )
{
for( auto && it : plist )
for( auto&& it : plist )
{
if( it.si.id == p.si.id && it.si.node == p.si.node )
return &it;
......@@ -3164,7 +3164,7 @@ namespace uniset
if( force_out )
return;
for( auto && m : d->pollmap )
for( auto&& m : d->pollmap )
{
auto& regmap = m.second;
......@@ -3229,7 +3229,7 @@ namespace uniset
if( !isWriteFunction(it.second->mbfunc) )
continue;
for( auto && i : it.second->slst )
for( auto&& i : it.second->slst )
{
if( sm->id == i.si.id && sm->node == i.si.node )
{
......@@ -3302,7 +3302,7 @@ namespace uniset
d->prev_numreply.store(d->numreply);
for( auto && m : d->pollmap )
for( auto&& m : d->pollmap )
{
if( m.first > 1 && (ncycle % m.first) != 0 )
continue;
......
......@@ -62,7 +62,6 @@ namespace uniset
- \b exchangeModeID - датчик(name) определяющий режим работы (см. MBExchange::ExchangeMode).
Секция <DeviceList> позволяет задать параметры обмена с конкретным RTU-устройством.
- \b addr - адрес устройства для которого, задаются параметры
- \b timeout msec - таймаут, для определения отсутствия связи
- \b invert - инвертировать логику. По умолчанию датчик выставляется в "1" при \b наличии связи.
......@@ -76,65 +75,41 @@ namespace uniset
При создании объекта в конструкторе передаётся префикс для определения параметров командной строки.
По умолчанию \b xxx="mbtcp".
Далее приведены основные параметры:
- \b --xxx-name ID - идентификатор(name) процесса.
IP-адрес шлюза задаётся параметром в конфигурационном файле \b gateway_iaddr или параметром командной строки \b --xxx-gateway-iaddr.
Порт задаётся в конфигурационном файле параметром \b gateway_port или параметром командной строки \b --xxx-gateway-port. По умолчанию используется порт \b 502.
\b --xxx-name ID - идентификатор(name) процесса.
IP-адрес шлюза задаётся параметром в конфигурационном файле \b gateway_iaddr или
параметром командной строки \b --xxx-gateway-iaddr.
Порт задаётся в конфигурационном файле параметром \b gateway_port или
параметром командной строки \b --xxx-gateway-port. По умолчанию используется порт \b 502.
\b --xxx-recv-timeout или \b recv_timeout msec - таймаут на приём одного сообщения. По умолчанию 100 мсек.
\b --xxx-timeout или \b timeout msec - таймаут на определение отсутствия связи
(после этого идёт попытка реинициализировать соединение)
По умолчанию 5000 мсек.
\b --xxx-reinit-timeout или \b reinit_timeout msec - таймаут на реинициализацию канала связи (после потери связи)
По умолчанию timeout.
\b --xxx-no-query-optimization или \b no_query_optimization - [1|0] отключить оптимизацию запросов
- \b --xxx-recv-timeout или \b recv_timeout msec - таймаут на приём одного сообщения. По умолчанию 100 мсек.
- \b --xxx-timeout или \b timeout msec - таймаут на определение отсутствия связи (после этого идёт попытка реинициализировать соединение). По умолчанию 5000 мсек.
- \b --xxx-reinit-timeout или \b reinit_timeout msec - таймаут на реинициализацию канала связи (после потери связи). По умолчанию timeout.
- \b --xxx-no-query-optimization или \b no_query_optimization- [1|0] отключить оптимизацию запросов
Оптимизация заключается в том, что регистры идущие подряд автоматически запрашиваются/записываются одним запросом.
В связи с чем, функция указанная в качестве \b mbfunc игнорируется и подменяется на работающую с многими регистрами.
\b --xxx-poll-time или \b poll_time msec - пауза между опросами. По умолчанию 100 мсек.
\b --xxx-initPause или \b initPause msec - пауза перед началом работы, после активации. По умолчанию 50 мсек.
\b --xxx-force или \b force [1|0]
- \b --xxx-poll-time или \b poll_time msec - пауза между опросами. По умолчанию 100 мсек.
- \b --xxx-initPause или \b initPause msec - пауза перед началом работы, после активации. По умолчанию 50 мсек.
- \b --xxx-force или \b force [1|0]
- 1 - перечитывать значения входов из SharedMemory на каждом цикле
- 0 - обновлять значения только по изменению
\b --xxx-persistent-connection или \b persistent_connection - НЕ закрывать соединение после каждого запроса.
\b --xxx-force-out или \b force_out [1|0]
- \b --xxx-persistent-connection или \b persistent_connection - НЕ закрывать соединение после каждого запроса.
- \b --xxx-force-out или \b force_out [1|0]
- 1 - перечитывать значения выходов из SharedMemory на каждом цикле
- 0 - обновлять значения только по изменению
\b --xxx-reg-from-id или \b reg_from_id [1|0]
- \b --xxx-reg-from-id или \b reg_from_id [1|0]
- 1 - в качестве регистра использовать идентификатор датчика
- 0 - регистр брать из поля tcp_mbreg
\b --xxx-heartbeat-id или \b heartbeat_id ID - название для датчика "сердцебиения" (см. \ref sec_SM_HeartBeat)
\b --xxx-heartbeat-max или \b heartbeat_max val - сохраняемое значение счётчика "сердцебиения".
\b --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
- \b --xxx-heartbeat-id или \b heartbeat_id ID - название для датчика "сердцебиения" (см. \ref sec_SM_HeartBeat)
- \b --xxx-heartbeat-max или \b heartbeat_max val - сохраняемое значение счётчика "сердцебиения".
- \b --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
\section sec_MBTCP_ConfList Конфигурирование списка регистров для ModbusTCP master
Конфигурационные параметры задаются в секции <sensors> конфигурационного файла.
Список обрабатываемых регистров задаётся при помощи двух параметров командной строки
\b --xxx-filter-field - задаёт фильтрующее поле для датчиков
\b --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
\b --xxx-statistic-sec sec - при наличии выведет кол-во посланных запросов за этот промежуток времени.
\b --xxx-set-prop-prefix [str] - Использовать 'str' в качестве префикса для свойств.
- \b --xxx-filter-field - задаёт фильтрующее поле для датчиков
- \b --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
- \b --xxx-statistic-sec sec - при наличии выведет кол-во посланных запросов за этот промежуток времени.
- \b --xxx-set-prop-prefix [str] - Использовать 'str' в качестве префикса для свойств.
Если не указать 'str' будет использован пустой префикс.
Если параметры не заданы, будет произведена попытка загрузить все датчики, у которых
......@@ -146,9 +121,7 @@ namespace uniset
\code
<sensors name="Sensors">
...
<item name="MySensor_S" textname="my sesnsor" iotype="DI"
tcp_mbtype="rtu" tcp_mbaddr="0x01" tcp_mbfunc="0x04" tcp_mbreg="0x02" my_tcp="1"
/>
<item name="MySensor_S" textname="my sesnsor" iotype="DI" tcp_mbtype="rtu" tcp_mbaddr="0x01" tcp_mbfunc="0x04" tcp_mbreg="0x02" my_tcp="1"/>
...
</sensors>
\endcode
......@@ -169,9 +142,9 @@ namespace uniset
Помимо этого можно задавать следующие параметры:
- \b tcp_vtype - тип переменной. см VTypes::VType.
- \b tcp_rawdata - [0|1] - игнорировать или нет параметры калибровки (cmin,cmax,rmin,rmax,presicion,caldiagram)
- \b tcp_rawdata- [0|1] - игнорировать или нет параметры калибровки (cmin,cmax,rmin,rmax,presicion,caldiagram)
- \b tcp_iotype - [DI,DO,AI,AO] - переназначить тип датчика. По умолчанию используется поле iotype.
- \b tcp_nbit - номер бита в слове. Используется для DI,DO в случае когда для опроса используется
- \b tcp_nbit- номер бита в слове. Используется для DI,DO в случае когда для опроса используется
функция читающая слова (03
- \b tcp_nbyte - [1|2] номер байта. Используется если tcp_vtype="byte".
- \b tcp_mboffset - "сдвиг"(может быть отрицательным) при опросе/записи.
......@@ -179,9 +152,9 @@ namespace uniset
- \b tcp_pollfactor - [0...n] Частота опроса. n задаёт "частоту" опроса. т.е. опрос каждые 1...n циклов
Для инициализации "выходов" (регистров которые пишутся) можно использовать поля:
- \b tcp_preinit - [0|1] считать регистр перед использованием (при запуске процесса)
- \b tcp_preinit- [0|1] считать регистр перед использованием (при запуске процесса)
- \b tcp_init_mbfunc - Номер функции для инициализации. Если не указана, будет определена автоматически исходя из tcp_mbfunc.
- \b tcp_init_mbreg - Номер регистра откуда считывать значение для инициализации. Если это поле не указано используется tcp_mbreg.
- \b tcp_init_mbreg- Номер регистра откуда считывать значение для инициализации. Если это поле не указано используется tcp_mbreg.
Если указано tcp_preinit="1", то прежде чем начать писать регистр в устройство, будет произведено его чтение.
......@@ -206,7 +179,7 @@ namespace uniset
- \b emSkipExchnage - отключить обмен (при этом данные "из SM" обновляются).
Режимы переключаются при помощи датчика, который можно задать либо аргументом командной строки
\b --prefix-exchange-mode-id либо в конф. файле параметром \b exchangeModeID="". Константы определяющие режимы объявлены в MBTCPMaster::ExchangeMode.
- \b --prefix-exchange-mode-id либо в конф. файле параметром \b exchangeModeID="". Константы определяющие режимы объявлены в MBTCPMaster::ExchangeMode.
\section sec_MBTCP_SafeMode Управление режимом "безопасного состояния"
В MBTCPMaster заложена возможность управлять режимом выставления безопасного состояния входов и выходов.
......
......@@ -259,7 +259,7 @@ std::shared_ptr<ModbusClient> MBTCPMultiMaster::initMB( bool reopen )
{
// сперва надо обновить все ignore
// т.к. фактически флаги выставляются и сбрасываются только здесь
for( auto && it : mblist )
for( auto&& it : mblist )
it->ignore = !it->ptIgnoreTimeout.checkTime();
// если reopen=true - значит почему-то по текущему каналу связи нет (хотя соединение есть)
......@@ -501,7 +501,7 @@ void MBTCPMultiMaster::check_thread()
{
while( isProcActive() )
{
for( auto && it : mblist )
for( auto&& it : mblist )
{
try
{
......@@ -575,7 +575,7 @@ void MBTCPMultiMaster::initIterators()
{
MBExchange::initIterators();
for( auto && it : mblist )
for( auto&& it : mblist )
shm->initIterator(it->respond_it);
}
// -----------------------------------------------------------------------------
......@@ -678,7 +678,7 @@ void MBTCPMultiMaster::initCheckConnectionParameters()
<< endl;
// инициализируем..
for( auto && m : mblist )
for( auto&& m : mblist )
{
m->checkFunc = checkFunc;
m->checkAddr = checkAddr;
......
......@@ -99,75 +99,56 @@ namespace uniset
При создании объекта в конструкторе передаётся префикс для определения параметров командной строки.
По умолчанию \b xxx="mbtcp".
Далее приведены основные параметры:
- \b --xxx-name ID - идентификатор процесса.
\b --xxx-name ID - идентификатор процесса.
IP-адрес шлюза задаётся параметром в конфигурационном файле \b gateway_iaddr или
параметром командной строки \b --xxx-gateway-iaddr.
IP-адрес шлюза задаётся параметром в конфигурационном файле \b gateway_iaddr или параметром командной строки \b --xxx-gateway-iaddr.
Порт задаётся в конфигурационном файле параметром \b gateway_port или
параметром командной строки \b --xxx-gateway-port. По умолчанию используется порт \b 502.
\b --xxx-recv-timeout или \b recv_timeout msec - таймаут на приём одного сообщения. По умолчанию 100 мсек.
\b --xxx-timeout или \b timeout msec - таймаут на определение отсутствия связи
- \b --xxx-recv-timeout или \b recv_timeout msec - таймаут на приём одного сообщения. По умолчанию 100 мсек.
- \b --xxx-timeout или \b timeout msec - таймаут на определение отсутствия связи
(после этого идёт попытка реинициализировать соединение)
По умолчанию 5000 мсек.
\b --xxx-reinit-timeout или \b reinit_timeout msec - таймаут на реинициализацию канала связи (после потери связи)
- \b --xxx-reinit-timeout или \b reinit_timeout msec - таймаут на реинициализацию канала связи (после потери связи)
По умолчанию timeout мсек.
\b --xxx-no-query-optimization или \b no_query_optimization - [1|0] отключить оптимизацию запросов
- \b --xxx-no-query-optimization или \b no_query_optimization - [1|0] отключить оптимизацию запросов
Оптимизация заключается в том, что регистры идущие подряд автоматически запрашиваются/записываются одним запросом.
В связи с чем, функция указанная в качестве \b mbfunc игнорируется и подменяется на работающую с многими регистрами.
\b --xxx-polltime или \b polltime msec - пауза между опросами. По умолчанию 100 мсек.
\b --xxx-checktime или \b checktime msec - пауза между проверками связи по разным каналам. По умолчанию 5000 мсек.
- \b --xxx-polltime или \b polltime msec - пауза между опросами. По умолчанию 100 мсек.
- \b --xxx-checktime или \b checktime msec - пауза между проверками связи по разным каналам. По умолчанию 5000 мсек.
Если задать <=0, то каналы будут просто переключаться по кругу (по timeout-у) в соответсвии с приоритетом (см. <GateList>).
Если >0, то происходит проверка связи (раз в checktime) по всем каналам (см. <GateList>) и в случае потери связи,
происходит переключение на следующий канал, по которому связь есть.
\b --xxx-initPause или \b initPause msec - пауза перед началом работы, после активации. По умолчанию 50 мсек.
\b --xxx-force или \b force [1|0]
- \b --xxx-initPause или \b initPause msec - пауза перед началом работы, после активации. По умолчанию 50 мсек.
- \b --xxx-force или \b force [1|0]
- 1 - перечитывать значения входов из SharedMemory на каждом цикле
- 0 - обновлять значения только по изменению
\b --xxx-persistent-connection или \b persistent_connection - НЕ закрывать соединение после каждого запроса.
\b --xxx-force-out или \b force_out [1|0]
- \b --xxx-persistent-connection или \b persistent_connection - НЕ закрывать соединение после каждого запроса.
- \b --xxx-force-out или \b force_out [1|0]
- 1 - перечитывать значения выходов из SharedMemory на каждом цикле
- 0 - обновлять значения только по изменению
\b --xxx-reg-from-id или \b reg_from_id [1|0]
- \b --xxx-reg-from-id или \b reg_from_id [1|0]
- 1 - в качестве регистра использовать идентификатор датчика
- 0 - регистр брать из поля tcp_mbreg
\b --xxx-heartbeat-id или \b heartbeat_id ID - идентификатор датчика "сердцебиения" (см. \ref sec_SM_HeartBeat)
\b --xxx-heartbeat-max или \b heartbeat_max val - сохраняемое значение счётчика "сердцебиения".
\b --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
\b --xxx-check-func [1,2,3,4] - Номер функции для проверки соединения
\b --xxx-check-addr [1..255 ] - Адрес устройства для проверки соединения
\b --xxx-check-reg [1..65535] - Регистр для проверки соединения
\b --xxx-check-init-from-regmap - Взять адрес, функцию и регистр для проверки связи из списка опроса
- \b --xxx-heartbeat-id или \b heartbeat_id ID - идентификатор датчика "сердцебиения" (см. \ref sec_SM_HeartBeat)
- \b --xxx-heartbeat-max или \b heartbeat_max val - сохраняемое значение счётчика "сердцебиения".
- \b --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
- \b --xxx-check-func [1,2,3,4] - Номер функции для проверки соединения
- \b --xxx-check-addr [1..255 ] - Адрес устройства для проверки соединения
- \b --xxx-check-reg [1..65535] - Регистр для проверки соединения
- \b --xxx-check-init-from-regmap - Взять адрес, функцию и регистр для проверки связи из списка опроса
\section sec_MBTCPM_ConfList Конфигурирование списка регистров для ModbusTCP master
Конфигурационные параметры задаются в секции <sensors> конфигурационного файла.
Список обрабатываемых регистров задаётся при помощи двух параметров командной строки
\b --xxx-filter-field - задаёт фильтрующее поле для датчиков
\b --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
\b --xxx-statistic-sec sec - при наличии выведет кол-во посланных запросов за этот промежуток времени.
\b --xxx-set-prop-prefix [str] - Использовать 'str' в качестве префикса для свойств.
Если не указать 'str' будет использован пустой префикс.
- \b --xxx-filter-field - задаёт фильтрующее поле для датчиков
- \b --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
- \b --xxx-statistic-sec sec - при наличии выведет кол-во посланных запросов за этот промежуток времени.
- \b --xxx-set-prop-prefix [str] - Использовать 'str' в качестве префикса для свойств. Если не указать 'str' будет использован пустой префикс.
Если параметры не заданы, будет произведена попытка загрузить все датчики, у которых
присутствуют необходимые настроечные параметры.
......@@ -193,15 +174,15 @@ namespace uniset
(например для "tcp_mbreg" должен быть задан --xxx-set-prop-prefix tcp_ ).
К основным параметрам относятся следующие (префикс \b tcp_ - для примера):
- \b tcp_mbtype - [rtu] - пока едиственный разрешённый тип.
- \b tcp_mbaddr - адрес RTU-устройства.
- \b tcp_mbtype- [rtu] - пока едиственный разрешённый тип.
- \b tcp_mbaddr- адрес RTU-устройства.
- \b tcp_mbreg - запрашиваемый/записываемый регистр.
- \b tcp_mbfunc - [0x1,0x2,0x3,...] функция опроса/записи. Разрешённые см. ModbusRTU::SlaveFunctionCode.
- \b tcp_mbfunc- [0x1,0x2,0x3,...] функция опроса/записи. Разрешённые см. ModbusRTU::SlaveFunctionCode.
Помимо этого можно задавать следующие параметры:
- \b tcp_vtype - тип переменной. см VTypes::VType.
- \b tcp_rawdata - [0|1] - игнорировать или нет параметры калибровки
- \b tcp_iotype - [DI,DO,AI,AO] - переназначить тип датчика. По умолчанию используется поле iotype.
- \b tcp_iotype- [DI,DO,AI,AO] - переназначить тип датчика. По умолчанию используется поле iotype.
- \b tcp_nbit - номер бита в слове. Используется для DI,DO в случае когда для опроса используется
функция читающая слова (03
- \b tcp_nbyte - [1|2] номер байта. Используется если tcp_vtype="byte".
......@@ -218,7 +199,7 @@ namespace uniset
По умолчанию все "записываемые" регистры инициализируются значением из SM. Т.е. пока не будет первый раз считано значение из SM,
регистры в устройство писатся не будут. Чтобы отключить это поведение, можно указать параметр
- \b tcp_sm_initOK - [0|1] Игнорировать начальную инициализацию из SM (сразу писать в устройство)
- \b tcp_sm_initOK- [0|1] Игнорировать начальную инициализацию из SM (сразу писать в устройство)
При этом будет записывыться значение "default".
......
......@@ -283,14 +283,14 @@ bool RTUExchange::poll()
dlog3 << myname << "(poll): ask addr=" << ModbusRTU::addr2str(d->mbaddr)
<< " regs=" << d->pollmap.size() << endl;
for( auto && m : d->pollmap )
for( auto&& m : d->pollmap )
{
if( m.first != 0 && (ncycle % m.first) != 0 )
continue;
auto rmap = m.second;
for( auto && it = rmap->begin(); it != rmap->end(); ++it )
for( auto&& it = rmap->begin(); it != rmap->end(); ++it )
{
try
{
......@@ -329,7 +329,7 @@ bool RTUExchange::poll()
updateSM();
// check thresholds
for( auto && t : thrlist )
for( auto&& t : thrlist )
{
if( !isProcActive() )
return false;
......
......@@ -638,7 +638,7 @@ namespace uniset
startNotifyEvent.wait(locker);
}
for( auto && i : cmap )
for( auto&& i : cmap )
i.second.ptTimeout.reset();
tcpserver->setMaxSessions( sessMaxNum );
......@@ -922,7 +922,7 @@ namespace uniset
// -------------------------------------------------------------------------
void MBSlave::updateThresholds()
{
for( auto && i : thrlist )
for( auto&& i : thrlist )
{
try
{
......@@ -1079,7 +1079,7 @@ namespace uniset
// ------------------------------------------------------------------------------------------
void MBSlave::sensorInfo( const uniset::SensorMessage* sm )
{
for( auto && regs : iomap )
for( auto&& regs : iomap )
{
auto& rmap = regs.second;
......@@ -1507,7 +1507,7 @@ namespace uniset
// ------------------------------------------------------------------------------------------
void MBSlave::initIterators()
{
for( auto && regs : iomap )
for( auto&& regs : iomap )
{
auto& rmap = regs.second;
......@@ -1534,7 +1534,7 @@ namespace uniset
// for TCPServer
shm->initIterator(sesscount_it);
for( auto && i : cmap )
for( auto&& i : cmap )
i.second.initIterators(shm);
}
// -----------------------------------------------------------------------------
......@@ -2014,6 +2014,7 @@ namespace uniset
}
ModbusRTU::DataGuard d(VTypes::F2r::wsize());
for( size_t k = 0; k < VTypes::F2r::wsize(); k++, i++ )
d.data[k] = dat[i];
......
......@@ -141,57 +141,41 @@ namespace uniset
По умолчанию \b xxx="mbs".
Далее приведены основные параметры:
\b --xxx-name ID - идентификатор процесса.
\b --xxx-default-mbaddr addr1 - slave-адрес по умолчанию для данного устройства. Если указан адрес 255 - ответ будет на любые сообщения.
\b --xxx-timeout или \b timeout msec - таймаут на определение отсутствия связи.
\b --xxx-reply-timeout msec - таймаут на формирование ответа.
\b --xxx-initPause или \b initPause msec - пауза перед началом работы, после активации. По умолчанию 50 мсек.
\b --xxx-force или \b force [1|0]
- \b --xxx-name ID - идентификатор процесса.
- \b --xxx-default-mbaddr addr1 - slave-адрес по умолчанию для данного устройства. Если указан адрес 255 - ответ будет на любы сообщения.
- \b --xxx-timeout или \b timeout msec - таймаут на определение отсутствия связи.
- \b --xxx-reply-timeout msec - таймаут на формирование ответа.
- \b --xxx-initPause или \b initPause msec - пауза перед началом работы, после активации. По умолчанию 50 мсек.
- \b --xxx-force или \b force [1|0]
- 1 - перечитывать/перезаписывать значения входов из SharedMemory на каждом цикле
- 0 - обновлять значения только по изменению
\b --xxx-reg-from-id или \b reg_from_id [1|0]
- \b --xxx-reg-from-id или \b reg_from_id [1|0]
- 1 - в качестве регистра использовать идентификатор датчика
- 0 - регистр брать из поля tcp_mbreg
\b --xxx-default-mbfunc или \b default_mbfunc [0...255] - Функция подставляемая по умолчанию, если не указан параметр mbfunc. Действует только если включён контроль функций (check-mbfunc).
\b --xxx-check-mbfunc [0|1] -
- 1 - включить контроль (обработку) свойства mbfunc. По умолчанию: отключёна. Если контроль включён то разрешено
использовать один и тот же регистр но \b для \b разных \b функций.
- \b --xxx-default-mbfunc или \b default_mbfunc [0...255] - Функция подставляемая по умолчанию, если не указан параметр mbfunc. Действует только если включён контроль функций (check-mbfunc).
- \b --xxx-check-mbfunc [0|1] -
- 1 - включить контроль (обработку) свойства mbfunc. По умолчанию: отключёна. Если контроль включён то разрешено использовать один и тот же регистр но \b для \b разных \b функций.
- 0 - игнорировать свойство mbfunc..
\b --xxx-heartbeat-id или \b heartbeat_id ID - идентификатор датчика "сердцебиения" (см. \ref sec_SM_HeartBeat)
\b --xxx-heartbeat-max или \b heartbeat_max val - сохраняемое значение счётчика "сердцебиения".
\b --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
\b --xxx-allow-setdatetime 0,1 - Включить функцию 0x50. Выставление даты и времени.
- \b --xxx-heartbeat-id или \b heartbeat_id ID - идентификатор датчика "сердцебиения" (см. \ref sec_SM_HeartBeat)
- \b --xxx-heartbeat-max или \b heartbeat_max val - сохраняемое значение счётчика "сердцебиения".
- \b --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
- \b --xxx-allow-setdatetime 0,1 - Включить функцию 0x50. Выставление даты и времени.
\par Настройки протокола RTU:
\b --xxx-dev devname - файл устройства
\b --xxx-speed - Скорость обмена (9600,19920,38400,57600,115200)
- \b --xxx-dev devname - файл устройства
- \b --xxx-speed- Скорость обмена (9600,19920,38400,57600,115200)
\par Настройки протокола TCP:
\b --xxx-inet-addr [xxx.xxx.xxx.xxx | hostname ] - this modbus server address
\b --xxx-inet-port num - this modbus server port. Default: 502.
- \b --xxx-inet-addr [xxx.xxx.xxx.xxx | hostname ] - this modbus server address
- \b --xxx-inet-port num - this modbus server port. Default: 502.
\section sec_MBSlave_ConfList Конфигурирование списка регистров для ModbusSlave
Конфигурационные параметры задаются в секции <sensors> конфигурационного файла.
Список обрабатываемых регистров задаётся при помощи двух параметров командной строки
\b --xxx-filter-field - задаёт фильтрующее поле для датчиков
\b --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
- \b --xxx-filter-field - задаёт фильтрующее поле для датчиков
- \b --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
\warning Если в результате список будет пустым, процесс завершает работу.
......@@ -199,12 +183,8 @@ namespace uniset
\code
<sensors name="Sensors">
...
<item name="MySensor_S" textname="my sesnsor" iotype="DI"
mbs="1" mbs_mbaddr="0x02" mbs_mbreg="1"
/>
<item name="MySensor2_S" textname="my sesnsor 2" iotype="DI"
mbs="1" mbs_mbaddr="0x01" mbs_mbreg="1"
/>
<item name="MySensor_S" textname="my sesnsor" iotype="DI" mbs="1" mbs_mbaddr="0x02" mbs_mbreg="1"/>
<item name="MySensor2_S" textname="my sesnsor 2" iotype="DI" mbs="1" mbs_mbaddr="0x01" mbs_mbreg="1"/>
...
</sensors>
\endcode
......@@ -212,25 +192,25 @@ namespace uniset
\warning По умолчанию для свойств используется заданный в конструктроре префикс "mbs_".
К основным параметрам настройки датчиков относятся следующие (префикс \b mbs_ - для примера):
- \b mbs_mbadrr - адрес к которому относиться данный регистр. Если не используется параметр \b default_mbaddr.
- \b mbs_mbaddr- адрес к которому относиться данный регистр. Если не используется параметр \b default_mbaddr.
- \b mbs_mbreg - запрашиваемый/записываемый регистр. Если не используется параметр \b reg_from_id.
Помимо этого можно задавать следующие параметры:
- \b mbs_vtype - тип переменной. см VTypes::VType.
- \b mbs_rawdata - [0|1] - игнорировать или нет параметры калибровки (cmin,cmax,rmin,rmax,presicion,caldiagram)
- \b mbs_iotype - [DI,DO,AI,AO] - переназначить тип датчика. По умолчанию используется поле iotype.
- \b mbs_iotype- [DI,DO,AI,AO] - переназначить тип датчика. По умолчанию используется поле iotype.
- \b mbs_nbyte - [1|2] номер байта. Используется если mbs_vtype="byte".
- \b accessmode - режим доступа к регистру.
"ro" - read only
"wo" - write only
"rw" - read/write. Режим по умолчанию.
- \b accessmode- режим доступа к регистру.
- "ro" - read only
- "wo" - write only
- "rw" - read/write. Режим по умолчанию.
\warning Регистр должен быть уникальным. И может повторятся только если указан параметр \a nbyte.
\section sec_MBSlave_FileTransfer Настройка передачи файлов в ModbusSlave (0x66)
Данная реализация позволяет передавать по протоколу Modbus заранее заданные файлы.
Настройка происходвится в конфигурационном файле.
Настройка производится в конфигурационном файле.
\code
<filelist>
<!-- Список файлов разрешённых для передачи по modbus
......@@ -292,6 +272,7 @@ namespace uniset
\section sec_MBSlave_DIAG Диагностические функции (0x08)
В процесс встроена поддержка диагностических функций. См. \ref uniset::ModbusRTU::DiagnosticsSubFunction
\section sec_MBSlave_TCP Настройка TCPServer
\code
......@@ -319,13 +300,12 @@ namespace uniset
\section sec_MBSlave_REST_API MBSlave HTTP API
/help - Получение списка доступных команд
/ - получение стандартной информации
/regs?regs=reg1,reg2,reg3,..&addr=addr1,addr2,addr3 - получение списка регистров
- \b/help- Получение списка доступных команд
- \b/- получение стандартной информации
- \b/regs?regs=reg1,reg2,reg3,..&addr=addr1,addr2,addr3 - получение списка регистров
Не обязательные параметры:
regs - выдать информацию только по указанным регистрам
addr - выдать информацию только по указанным адресам устройств
- regs - выдать информацию только по указанным регистрам
- addr - выдать информацию только по указанным адресам устройств
*/
// -----------------------------------------------------------------------------
/*! Реализация slave-интерфейса */
......
......@@ -422,7 +422,7 @@ RRDServer::RRDInfo::RRDInfo(const string& fname, long tmID, long sec, const RRDS
filename(fname), tid(tmID), sec(sec), dslist(lst)
{
// фомируем dsmap
for( auto && i : dslist )
for( auto&& i : dslist )
dsmap.emplace(i->sid, i);
}
// -----------------------------------------------------------------------------
......@@ -29,7 +29,7 @@ namespace uniset
{
// -----------------------------------------------------------------------------
/*!
\page page_RRDServer Реализация RRD хранилища
\page page_RRDServer (RRDServer) Реализация RRD хранилища
- \ref sec_RRD_Comm
- \ref sec_RRD_Conf
......@@ -60,8 +60,7 @@ namespace uniset
- \b filename - имя создаваемого rrd-файла
- \b filter_field - поле у датчика, определяющее, что его нужно сохранять в БД
- \b filter_value - значение \b filter_field, определяющее, что датчик нужно сохранять в БД
- \b ds_field - поле определяющее, параметр задающий формат хранения. Если \a ds_field не задано,
то будет браться filter_field+filter_value+'_ds'.
- \b ds_field - поле определяющее, параметр задающий формат хранения. Если \a ds_field не задано, то будет браться filter_field+filter_value+'_ds'.
- \b step - период обновления данных (в секундах)
- \b overwrite - [0,1]. Пересоздавать ли БД, если файл уже существует.
......@@ -81,6 +80,8 @@ namespace uniset
По умолчанию в качестве имени параметра берётся поле \b 'ds_field'_dsname='', если это поле не указано, то берётся \b name датчика.
\warning Имя не может превышать RRDServer::RRD_MAX_DSNAME_LEN.
*/
// -----------------------------------------------------------------------------
/*! Реализация хранения на основе RRD */
class RRDServer:
public UObject_SK
{
......
......@@ -335,7 +335,7 @@ namespace uniset
res = IONotifyController::activateObject();
// инициализируем указатели
for( auto && it : hblist )
for( auto&& it : hblist )
{
it.a_it = myioEnd();
it.d_it = myioEnd();
......@@ -343,13 +343,13 @@ namespace uniset
itPulsar = myioEnd();
for( auto && it : hist )
for( auto&& it : hist )
{
for( auto && hit : it.hlst )
for( auto&& hit : it.hlst )
hit.ioit = myioEnd();
}
for( auto && it : histmap )
for( auto&& it : histmap )
{
auto i = myiofind(it.first);
......@@ -386,7 +386,7 @@ namespace uniset
bool wdtpingOK = true;
for( auto && it : hblist )
for( auto&& it : hblist )
{
try
{
......@@ -433,7 +433,7 @@ namespace uniset
// ------------------------------------------------------------------------------------------
bool SharedMemory::readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec )
{
for( auto && r : lstRSlot )
for( auto&& r : lstRSlot )
{
try
{
......@@ -726,7 +726,7 @@ namespace uniset
// -----------------------------------------------------------------------------
void SharedMemory::checkHistoryFilter( UniXML::iterator& xit )
{
for( auto && it : hist )
for( auto&& it : hist )
{
if( xit.getProp(it.filter).empty() )
continue;
......@@ -759,9 +759,9 @@ namespace uniset
if( hist.empty() )
return;
for( auto && it : hist )
for( auto&& it : hist )
{
for( auto && hit : it.hlst )
for( auto&& hit : it.hlst )
{
try
{
......@@ -802,7 +802,7 @@ namespace uniset
<< " value=" << value
<< endl;
for( auto && it1 : (*lst) )
for( auto&& it1 : (*lst) )
{
History::iterator it = it1;
......
......@@ -39,10 +39,8 @@
namespace uniset
{
// -----------------------------------------------------------------------------
/*! \page page_SharedMemory Реализация разделяемой между процессами памяти (SharedMemory)
\section sec_SM_Common Задачи решаемые объектом SharedMemory
Класс SharedMemory расширяет набор задач класса IONotifyController.
......@@ -190,14 +188,14 @@ namespace uniset
У аналоговых датчиков "сердцебиения" в конфигурационном файле необходимо указывать \b heartbeat="1".
А также поля:
<br>\b heartbeat_ds_name - имя дискретного датчика, связанного с данным аналоговым
<br>\b heartbeat_node="ses" - фильтрующее поле (см. --heartbeat-node)
<br>\b heartbeat_reboot_msec - время ожидания перезапуска процесса. Это необязательный параметр, задаётся только в случае
- \b heartbeat_ds_name - имя дискретного датчика, связанного с данным аналоговым
- \b heartbeat_node="ses" - фильтрующее поле (см. --heartbeat-node)
- \b heartbeat_reboot_msec - время ожидания перезапуска процесса. Это необязательный параметр, задаётся только в случае
необходимости перезапуска контроллера.
Пример задания датчиков "сердцебиения":
<br>_31_04_AS - аналоговый (счётчик)
<br>_41_04_S - дискретный ("доступность процесса")
- _31_04_AS - аналоговый (счётчик)
- _41_04_S - дискретный ("доступность процесса")
\code
<item default="10" heartbeat="1" heartbeat_ds_name="_41_04_S" heartbeat_node="ses" heartbeat_reboot_msec="10000"
......@@ -241,12 +239,9 @@ namespace uniset
id - задаёт (внутренний) идентификатор "истории"
fuse_id - идентификатор датчика "детонатора"
fuse_value - значение срабатывания (для аналогового "детонатора")
fuse_invert - инвертировать (для дискретных "детонаторов").
Т.е. срабатывание на значение "0".
fuse_invert - инвертировать (для дискретных "детонаторов"). Т.е. срабатывание на значение "0".
size - количество точек в хранимой истории
filter - поле используемое в качестве фильтра, определяющего датчики
входящие в данную группу (историю).
filter - поле используемое в качестве фильтра, определяющего датчики входящие в данную группу (историю).
\endcode
Каждый датчик может входить в любое количество групп (историй).
......@@ -302,26 +297,26 @@ namespace uniset
\endcode
\section sec_SM_REST_API SharedMemory HTTP API
\code
/help - Получение списка доступных команд
/ - получение стандартной информации
/- получение стандартной информации
/get?id1,name2,id3,..&shortInfo - получение значений указанных датчиков
Не обязательные параметры:
shortInfo - выдать короткую информацию о датчике (id,value,real_value и когда менялся)
/sensors?offset=N&limit=M - получение полной информации по списку датчиков.
/sensors?offset=N&limit=M- получение полной информации по списку датчиков.
Не обязательные параметры:
offset - начиная с,
limit - количество в ответе.
/consumers?sens1,sens2,sens3 - получить список заказчиков по каждому датчику
Не обязательные параметры:
sens1,... - список по каким датчикам выдать ответ
/lost - получить список заказчиков с которыми терялась связь (и они удалялись из списка)
/conf/get?id,name,...&props=textname,iotype,... - Получить указанные параметры объектов (по id или name) из configure.xml.
Если props не указаны, то отдаются все поля какие есть.
\endcode
*/
// -----------------------------------------------------------------------------
/*! Реалиазция SharedMemory */
class SharedMemory:
public IONotifyController
{
......
......@@ -550,7 +550,7 @@ void UNetExchange::step() noexcept
}
}
for( auto && it : recvlist )
for( auto&& it : recvlist )
it.step(shm, myname, unetlog);
}
......@@ -758,10 +758,10 @@ void UNetExchange::askSensors( UniversalIO::UIOCommand cmd )
void UNetExchange::sensorInfo( const uniset::SensorMessage* sm )
{
if( sender )
sender->updateSensor( sm->id , sm->value );
sender->updateSensor( sm->id, sm->value );
if( sender2 )
sender2->updateSensor( sm->id , sm->value );
sender2->updateSensor( sm->id, sm->value );
}
// ------------------------------------------------------------------------------------------
bool UNetExchange::activateObject()
......@@ -842,7 +842,7 @@ void UNetExchange::initIterators() noexcept
if( sender2 )
sender2->initIterators();
for( auto && it : recvlist )
for( auto&& it : recvlist )
it.initIterators(shm);
}
// -----------------------------------------------------------------------------
......@@ -917,7 +917,7 @@ std::shared_ptr<UNetExchange> UNetExchange::init_unetexchange(int argc, const ch
// -----------------------------------------------------------------------------
void UNetExchange::receiverEvent( const shared_ptr<UNetReceiver>& r, UNetReceiver::Event ev ) noexcept
{
for( auto && it : recvlist )
for( auto&& it : recvlist )
{
if( it.r1 == r )
{
......
......@@ -144,6 +144,7 @@ namespace uniset
- unet_channelswitchcount_id="" - количество переключений с канала на канал
*/
// -----------------------------------------------------------------------------
/*! Реализация процесса обмена по протоколу UNet */
class UNetExchange:
public UniSetObject
{
......
......@@ -837,7 +837,7 @@ void UNetReceiver::initIterators() noexcept
{
CacheVec& d_icache(mit->second.cache);
for( auto && it : d_icache )
for( auto&& it : d_icache )
shm->initIterator(it.ioit);
}
......@@ -845,7 +845,7 @@ void UNetReceiver::initIterators() noexcept
{
CacheVec& a_icache(mit->second.cache);
for( auto && it : a_icache )
for( auto&& it : a_icache )
shm->initIterator(it.ioit);
}
}
......
......@@ -156,7 +156,7 @@ namespace uniset
// -----------------------------------------------------------------------------
void UNetSender::updateFromSM()
{
for( auto && it : items )
for( auto&& it : items )
{
UItem& i = it.second;
......@@ -243,7 +243,7 @@ namespace uniset
if( !shm->isLocalwork() )
updateFromSM();
for( auto && it : mypacks )
for( auto&& it : mypacks )
{
if( it.first > 1 && (ncycle % it.first) != 0 )
continue;
......@@ -504,6 +504,7 @@ namespace uniset
if( p.pack_ind >= maxAData )
{
anum++;
if( anum >= pk.size() )
pk.resize(anum + 1);
......@@ -551,7 +552,7 @@ namespace uniset
// -----------------------------------------------------------------------------
void UNetSender::initIterators()
{
for( auto && it : items )
for( auto&& it : items )
shm->initIterator(it.second.ioit);
}
// -----------------------------------------------------------------------------
......
......@@ -103,7 +103,7 @@ static void run_senders( size_t max, const std::string& s_host, size_t count = 5
if( packetnum == 0 )
packetnum = 1;
for( auto && udp : vsend )
for( auto&& udp : vsend )
{
try
{
......@@ -147,7 +147,7 @@ static void run_test( size_t max, const std::string& host )
size_t count = 0;
// Run receivers..
for( auto && r : vrecv )
for( auto&& r : vrecv )
{
if( r )
{
......@@ -161,7 +161,7 @@ static void run_test( size_t max, const std::string& host )
// wait..
pause();
for( auto && r : vrecv )
for( auto&& r : vrecv )
{
if(r)
r->stop();
......
......@@ -29,7 +29,7 @@ class UObject_SK:
public uniset::UniSetObject
{
public:
UObject_SK( uniset::ObjectId id, xmlNode* node=uniset::uniset_conf()->getNode("UObject"), const std::string& argprefix="", xmlNode* globalConfNode=nullptr );
UObject_SK( uniset::ObjectId id, xmlNode* node = uniset::uniset_conf()->getNode("UObject"), const std::string& argprefix = "", xmlNode* globalConfNode = nullptr );
UObject_SK();
virtual ~UObject_SK();
......@@ -43,54 +43,60 @@ class UObject_SK:
virtual bool setMsg( uniset::ObjectId code, bool state = true ) noexcept;
inline std::shared_ptr<DebugStream> log() noexcept { return mylog; }
inline std::shared_ptr<uniset::LogAgregator> logAgregator() noexcept { return loga; }
inline std::shared_ptr<DebugStream> log() noexcept
{
return mylog;
}
inline std::shared_ptr<uniset::LogAgregator> logAgregator() noexcept
{
return loga;
}
void init_dlog( std::shared_ptr<DebugStream> d ) noexcept;
// "синтаксический сахар"..для логов
#ifndef myinfo
#define myinfo if( log()->debugging(Debug::INFO) ) log()->info()
#endif
#ifndef mywarn
#define mywarn if( log()->debugging(Debug::WARN) ) log()->warn()
#endif
#ifndef mycrit
#define mycrit if( log()->debugging(Debug::CRIT) ) log()->crit()
#endif
#ifndef mylog1
#define mylog1 if( log()->debugging(Debug::LEVEL1) ) log()->level1()
#endif
#ifndef mylog2
#define mylog2 if( log()->debugging(Debug::LEVEL2) ) log()->level2()
#endif
#ifndef mylog3
#define mylog3 if( log()->debugging(Debug::LEVEL3) ) log()->level3()
#endif
#ifndef mylog4
#define mylog4 if( log()->debugging(Debug::LEVEL4) ) log()->level4()
#endif
#ifndef mylog5
#define mylog5 if( log()->debugging(Debug::LEVEL5) ) log()->level5()
#endif
#ifndef mylog6
#define mylog6 if( log()->debugging(Debug::LEVEL6) ) log()->level6()
#endif
#ifndef mylog7
#define mylog7 if( log()->debugging(Debug::LEVEL7) ) log()->level7()
#endif
#ifndef mylog8
#define mylog8 if( log()->debugging(Debug::LEVEL8) ) log()->level8()
#endif
#ifndef mylog9
#define mylog9 if( log()->debugging(Debug::LEVEL9) ) log()->level9()
#endif
#ifndef mylogany
#define mylogany log()->any()
#endif
#ifndef vmonit
#define vmonit( var ) vmon.add( #var, var )
#endif
#ifndef myinfo
#define myinfo if( log()->debugging(Debug::INFO) ) log()->info()
#endif
#ifndef mywarn
#define mywarn if( log()->debugging(Debug::WARN) ) log()->warn()
#endif
#ifndef mycrit
#define mycrit if( log()->debugging(Debug::CRIT) ) log()->crit()
#endif
#ifndef mylog1
#define mylog1 if( log()->debugging(Debug::LEVEL1) ) log()->level1()
#endif
#ifndef mylog2
#define mylog2 if( log()->debugging(Debug::LEVEL2) ) log()->level2()
#endif
#ifndef mylog3
#define mylog3 if( log()->debugging(Debug::LEVEL3) ) log()->level3()
#endif
#ifndef mylog4
#define mylog4 if( log()->debugging(Debug::LEVEL4) ) log()->level4()
#endif
#ifndef mylog5
#define mylog5 if( log()->debugging(Debug::LEVEL5) ) log()->level5()
#endif
#ifndef mylog6
#define mylog6 if( log()->debugging(Debug::LEVEL6) ) log()->level6()
#endif
#ifndef mylog7
#define mylog7 if( log()->debugging(Debug::LEVEL7) ) log()->level7()
#endif
#ifndef mylog8
#define mylog8 if( log()->debugging(Debug::LEVEL8) ) log()->level8()
#endif
#ifndef mylog9
#define mylog9 if( log()->debugging(Debug::LEVEL9) ) log()->level9()
#endif
#ifndef mylogany
#define mylogany log()->any()
#endif
#ifndef vmonit
#define vmonit( var ) vmon.add( #var, var )
#endif
// Вспомогательные функции для удобства логирования
// ------------------------------------------------------------
......@@ -107,23 +113,26 @@ class UObject_SK:
\param id - идентификатор датчика
\param showLinkName - TRUE - выводить SensorName, FALSE - не выводить
*/
std::string str( uniset::ObjectId id, bool showLinkName=true ) const;
std::string str( uniset::ObjectId id, bool showLinkName = true ) const;
/*! Вывод значения входа/выхода в формате: in_xxx(SensorName)=val
\param id - идентификатор датчика
\param showLinkName - TRUE - выводить SensorName, FALSE - не выводить
*/
std::string strval( uniset::ObjectId id, bool showLinkName=true ) const;
std::string strval( uniset::ObjectId id, bool showLinkName = true ) const;
/*! Вывод в строку названия датчика-сообщения: xxx(SensorName)
\param id - идентификатор датчика
\param showLinkName - TRUE - выводить SensorName, FALSE - не выводить
*/
std::string msgstr( uniset::ObjectId id, bool showLinkName=true ) const;
std::string msgstr( uniset::ObjectId id, bool showLinkName = true ) const;
/*! Вывод состояния внутренних переменных */
inline std::string dumpVars(){ return vmon.pretty_str(); }
inline std::string dumpVars()
{
return vmon.pretty_str();
}
// ------------------------------------------------------------
std::string help() const noexcept;
......@@ -165,17 +174,23 @@ class UObject_SK:
virtual void timerInfo( const uniset::TimerMessage* tm ) override {}
virtual bool activateObject() override;
virtual bool deactivateObject() override;
virtual std::string getMonitInfo() const { return ""; } /*!< пользовательская информация выводимая в getInfo() */
virtual std::string getTypeOfMessage( int t ) const { return uniset::strTypeOfMessage(t); } /*!< получение названия типа сообщения. Используется в getInfo() */
virtual std::string getMonitInfo() const
{
return ""; /*!< пользовательская информация выводимая в getInfo() */
}
virtual std::string getTypeOfMessage( int t ) const
{
return uniset::strTypeOfMessage(t); /*!< получение названия типа сообщения. Используется в getInfo() */
}
#ifndef DISABLE_REST_API
virtual void httpGetUserData( Poco::JSON::Object::Ptr& jdata ){} /*!< для пользовательских данных в httpGet() */
virtual void httpGetUserData( Poco::JSON::Object::Ptr& jdata ) {} /*!< для пользовательских данных в httpGet() */
virtual Poco::JSON::Object::Ptr httpDumpIO();
virtual Poco::JSON::Object::Ptr httpRequestLog( const Poco::URI::QueryParameters& p );
#endif
// Выполнение очередного шага программы
virtual void step(){}
virtual void step() {}
void preAskSensors( UniversalIO::UIOCommand cmd );
void preSysCommand( const uniset::SystemMessage* sm );
......@@ -204,9 +219,15 @@ class UObject_SK:
xmlNode* confnode;
/*! получить числовое свойство из конф. файла по привязанной confnode */
int getIntProp(const std::string& name) { return uniset::uniset_conf()->getIntProp(confnode, name); }
int getIntProp(const std::string& name)
{
return uniset::uniset_conf()->getIntProp(confnode, name);
}
/*! получить текстовое свойство из конф. файла по привязанной confnode */
inline const std::string getProp(const std::string& name) { return uniset::uniset_conf()->getProp(confnode, name); }
inline const std::string getProp(const std::string& name)
{
return uniset::uniset_conf()->getProp(confnode, name);
}
uniset::timeout_t smReadyTimeout; /*!< время ожидания готовности SM */
std::atomic_bool activated = { false };
......@@ -258,10 +279,10 @@ class UObject_SK:
}
};
std::unordered_map<const uniset::ObjectId,size_t, StatHashFn> smStat; /*!< количество сообщений по датчикам */
std::unordered_map<const uniset::ObjectId, size_t, StatHashFn> smStat; /*!< количество сообщений по датчикам */
size_t processingMessageCatchCount = { 0 }; /*!< количество исключений пойманных в processingMessage */
std::unordered_map<long,size_t> msgTypeStat; /*!< количество сообщений по типам */
std::unordered_map<long, size_t> msgTypeStat; /*!< количество сообщений по типам */
std::string ostate = { "" }; /*!< состояние процесса (выводится в getInfo()) */
......
......@@ -143,7 +143,7 @@ namespace uniset
}
// ----------------------------------------------------------------------------
Calibration::Calibration(xmlNode* node , size_t reserv ):
Calibration::Calibration(xmlNode* node, size_t reserv ):
minRaw(0), maxRaw(0), minVal(0), maxVal(0), rightVal(0), leftVal(0), rightRaw(0), leftRaw(0),
szCache(5),
numCacheResort(20),
......
......@@ -93,26 +93,26 @@ using namespace uniset;
throw uniset::TimeOut(); \
} \
// --------------------------------------------------------------------------
SMInterface::SMInterface( uniset::ObjectId _shmID, const std::shared_ptr<UInterface>& _ui,
// --------------------------------------------------------------------------
SMInterface::SMInterface( uniset::ObjectId _shmID, const std::shared_ptr<UInterface>& _ui,
uniset::ObjectId _myid, const std::shared_ptr<IONotifyController> ic ):
ic(ic),
ui(_ui),
oref( CORBA::Object::_nil() ),
shmID(_shmID),
myid(_myid)
{
{
if( shmID == DefaultObjectId )
throw uniset::SystemError("(SMInterface): Unknown shmID!" );
}
// --------------------------------------------------------------------------
SMInterface::~SMInterface()
{
}
// --------------------------------------------------------------------------
SMInterface::~SMInterface()
{
}
// --------------------------------------------------------------------------
void SMInterface::setValue( uniset::ObjectId id, long value )
{
}
// --------------------------------------------------------------------------
void SMInterface::setValue( uniset::ObjectId id, long value )
{
if( ic )
{
BEG_FUNC1(SMInterface::setValue)
......@@ -129,10 +129,10 @@ using namespace uniset;
ui->setValue(si, value, myid);
return;
END_FUNC(SMInterface::setValue)
}
// --------------------------------------------------------------------------
long SMInterface::getValue( uniset::ObjectId id )
{
}
// --------------------------------------------------------------------------
long SMInterface::getValue( uniset::ObjectId id )
{
if( ic )
{
BEG_FUNC1(SMInterface::getValue)
......@@ -143,10 +143,10 @@ using namespace uniset;
BEG_FUNC1(SMInterface::getValue)
return ui->getValue(id);
END_FUNC(SMInterface::getValue)
}
// --------------------------------------------------------------------------
void SMInterface::askSensor( uniset::ObjectId id, UniversalIO::UIOCommand cmd, uniset::ObjectId backid )
{
}
// --------------------------------------------------------------------------
void SMInterface::askSensor( uniset::ObjectId id, UniversalIO::UIOCommand cmd, uniset::ObjectId backid )
{
ConsumerInfo_var ci;
ci->id = (backid == DefaultObjectId) ? myid : backid;
ci->node = ui->getConf()->getLocalNode();
......@@ -163,10 +163,10 @@ using namespace uniset;
ui->askRemoteSensor(id, cmd, conf->getLocalNode(), ci->id);
return;
END_FUNC(SMInterface::askSensor)
}
// --------------------------------------------------------------------------
IOController_i::SensorInfoSeq* SMInterface::getSensorsMap()
{
}
// --------------------------------------------------------------------------
IOController_i::SensorInfoSeq* SMInterface::getSensorsMap()
{
if( ic )
{
BEG_FUNC1(SMInterface::getSensorsMap)
......@@ -177,10 +177,10 @@ using namespace uniset;
BEG_FUNC(SMInterface::getSensorsMap)
return shm->getSensorsMap();
END_FUNC(SMInterface::getSensorsMap)
}
// --------------------------------------------------------------------------
IONotifyController_i::ThresholdsListSeq* SMInterface::getThresholdsList()
{
}
// --------------------------------------------------------------------------
IONotifyController_i::ThresholdsListSeq* SMInterface::getThresholdsList()
{
if( ic )
{
BEG_FUNC1(SMInterface::getThresholdsList)
......@@ -191,11 +191,11 @@ using namespace uniset;
BEG_FUNC(SMInterface::getThresholdsList)
return shm->getThresholdsList();
END_FUNC(SMInterface::getThresholdsList)
}
// --------------------------------------------------------------------------
void SMInterface::setUndefinedState( const IOController_i::SensorInfo& si, bool undefined,
}
// --------------------------------------------------------------------------
void SMInterface::setUndefinedState( const IOController_i::SensorInfo& si, bool undefined,
uniset::ObjectId sup_id )
{
{
if( ic )
{
BEG_FUNC1(SMInterface::setUndefinedState)
......@@ -208,10 +208,10 @@ using namespace uniset;
shm->setUndefinedState(si.id, undefined, sup_id);
return;
END_FUNC(SMInterface::setUndefinedState)
}
// --------------------------------------------------------------------------
bool SMInterface::exist()
{
}
// --------------------------------------------------------------------------
bool SMInterface::exist()
{
if( ic )
{
BEG_FUNC1(SMInterface::exist)
......@@ -220,37 +220,37 @@ using namespace uniset;
}
return ui->isExist(shmID);
}
// --------------------------------------------------------------------------
IOController::IOStateList::iterator SMInterface::ioEnd()
{
}
// --------------------------------------------------------------------------
IOController::IOStateList::iterator SMInterface::ioEnd()
{
CHECK_IC_PTR(ioEnd)
return ic->ioEnd();
}
// --------------------------------------------------------------------------
void SMInterface::localSetValue( IOController::IOStateList::iterator& it,
}
// --------------------------------------------------------------------------
void SMInterface::localSetValue( IOController::IOStateList::iterator& it,
uniset::ObjectId sid,
CORBA::Long value, uniset::ObjectId sup_id )
{
{
if( !ic )
return setValue(sid, value);
ic->localSetValueIt(it, sid, value, sup_id);
}
// --------------------------------------------------------------------------
long SMInterface::localGetValue( IOController::IOStateList::iterator& it, uniset::ObjectId sid )
{
}
// --------------------------------------------------------------------------
long SMInterface::localGetValue( IOController::IOStateList::iterator& it, uniset::ObjectId sid )
{
if( !ic )
return getValue( sid );
// CHECK_IC_PTR(localGetValue)
return ic->localGetValue(it, sid);
}
// --------------------------------------------------------------------------
void SMInterface::localSetUndefinedState( IOController::IOStateList::iterator& it,
}
// --------------------------------------------------------------------------
void SMInterface::localSetUndefinedState( IOController::IOStateList::iterator& it,
bool undefined,
uniset::ObjectId sid )
{
{
// CHECK_IC_PTR(localSetUndefinedState)
if( !ic )
{
......@@ -262,22 +262,22 @@ using namespace uniset;
}
ic->localSetUndefinedState(it, undefined, sid);
}
// --------------------------------------------------------------------------
void SMInterface::initIterator( IOController::IOStateList::iterator& it )
{
}
// --------------------------------------------------------------------------
void SMInterface::initIterator( IOController::IOStateList::iterator& it )
{
if( ic )
it = ic->ioEnd();
}
// --------------------------------------------------------------------------
bool SMInterface::waitSMready( int ready_timeout, int pmsec )
{
}
// --------------------------------------------------------------------------
bool SMInterface::waitSMready( int ready_timeout, int pmsec )
{
std::atomic_bool cancelFlag = { false };
return waitSMreadyWithCancellation(ready_timeout, cancelFlag, pmsec);
}
// --------------------------------------------------------------------------
bool SMInterface::waitSMworking( uniset::ObjectId sid, int msec, int pmsec )
{
}
// --------------------------------------------------------------------------
bool SMInterface::waitSMworking( uniset::ObjectId sid, int msec, int pmsec )
{
PassiveTimer ptSMready(msec);
bool sm_ready = false;
......@@ -295,10 +295,10 @@ using namespace uniset;
}
return sm_ready;
}
// --------------------------------------------------------------------------
bool SMInterface::waitSMreadyWithCancellation(int ready_timeout, std::atomic_bool& cancelFlag, int pmsec)
{
}
// --------------------------------------------------------------------------
bool SMInterface::waitSMreadyWithCancellation(int ready_timeout, std::atomic_bool& cancelFlag, int pmsec)
{
PassiveTimer ptSMready(ready_timeout);
bool sm_ready = false;
......@@ -317,11 +317,11 @@ using namespace uniset;
}
return sm_ready;
}
// --------------------------------------------------------------------------
}
// --------------------------------------------------------------------------
#ifndef DISABLE_REST_API
std::string SMInterface::apiRequest( const std::string& query )
{
std::string SMInterface::apiRequest( const std::string& query )
{
if( ic )
{
BEG_FUNC1(SMInterface::apiRequest)
......@@ -334,6 +334,6 @@ using namespace uniset;
SimpleInfo_var i = shm->apiRequest(query.c_str());
return std::string(i->info);
END_FUNC(SMInterface::apiRequest)
}
}
#endif
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
......@@ -32,28 +32,28 @@ using namespace uniset;
// -----------------------------------------------------------------------------
UObject_SK::UObject_SK():
// Инициализация идентификаторов (имена берутся из конф. файла)
// Инициализация идентификаторов (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// variables (public and proteced)
// variables (public and proteced)
// ------------------
active(false),
// ------------------
active(false),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(0),
smReadyTimeout(0),
activated(false),
askPause(2000),
forceOut(false),
// private variables
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(0),
smReadyTimeout(0),
activated(false),
askPause(2000),
forceOut(false),
// private variables
end_private(false)
end_private(false)
{
mycrit << "UObject: init failed!!!!!!!!!!!!!!!" << endl;
throw uniset::Exception( std::string(myname+": init failed!!!") );
throw uniset::Exception( std::string(myname + ": init failed!!!") );
}
// -----------------------------------------------------------------------------
// ( val, confval, globalval, default val )
......@@ -62,6 +62,7 @@ static const std::string init4_str( const std::string& s1, const std::string& s2
{
if( !s1.empty() )
return s1;
if( !s2.empty() )
return s2;
......@@ -76,6 +77,7 @@ static const std::string init3_str( const std::string& s1, const std::string& s2
{
if( !s1.empty() )
return s1;
if( !s2.empty() )
return s2;
......@@ -89,41 +91,41 @@ static uniset::ObjectId init_node( xmlNode* cnode, const std::string& prop )
auto conf = uniset_conf();
if( conf->getProp(cnode,prop).empty() )
if( conf->getProp(cnode, prop).empty() )
return conf->getLocalNode();
return conf->getNodeID(conf->getProp(cnode,prop));
return conf->getNodeID(conf->getProp(cnode, prop));
}
// -----------------------------------------------------------------------------
UObject_SK::UObject_SK( ObjectId id, xmlNode* cnode, const std::string& _argprefix, xmlNode* globalnode ):
UniSetObject(id),
// Инициализация идентификаторов (имена берутся из конф. файла)
UniSetObject(id),
// Инициализация идентификаторов (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// Используемые идентификаторы сообщений (имена берутся из конф. файла)
// variables
// variables
sleep_msec(150),
active(true),
argprefix( (_argprefix.empty() ? myname+"-" : _argprefix) ),
sleep_msec(150),
active(true),
argprefix( (_argprefix.empty() ? myname + "-" : _argprefix) ),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(cnode),
smReadyTimeout(0),
activated(false),
askPause(uniset_conf()->getPIntProp(cnode,"askPause",2000)),
forceOut(false),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(cnode),
smReadyTimeout(0),
activated(false),
askPause(uniset_conf()->getPIntProp(cnode, "askPause", 2000)),
forceOut(false),
end_private(false)
end_private(false)
{
auto conf = uniset_conf();
if( uniset::findArgParam("--print-id-list",uniset_conf()->getArgc(),uniset_conf()->getArgv()) != -1 )
if( uniset::findArgParam("--print-id-list", uniset_conf()->getArgc(), uniset_conf()->getArgv()) != -1 )
{
// abort();
// abort();
}
......@@ -139,10 +141,10 @@ end_private(false)
{
ostringstream s;
s << argprefix << "log";
conf->initLogStream(mylog,s.str());
conf->initLogStream(mylog, s.str());
}
loga = make_shared<LogAgregator>(myname+"-loga");
loga = make_shared<LogAgregator>(myname + "-loga");
loga->add(mylog);
loga->add(ulog());
......@@ -160,12 +162,14 @@ end_private(false)
logserv_port = conf->getArgPInt("--" + argprefix + "logserver-port", it.getProp("logserverPort"), getId());
}
forceOut = conf->getArgPInt("--" + argprefix + "force-out",it.getProp("forceOut"),false);
forceOut = conf->getArgPInt("--" + argprefix + "force-out", it.getProp("forceOut"), false);
string heart = conf->getArgParam("--" + argprefix + "heartbeat-id", it.getProp("heartbeat_id"));
string heart = conf->getArgParam("--" + argprefix + "heartbeat-id",it.getProp("heartbeat_id"));
if( !heart.empty() )
{
idHeartBeat = conf->getSensorID(heart);
if( idHeartBeat == DefaultObjectId )
{
ostringstream err;
......@@ -173,13 +177,14 @@ end_private(false)
throw uniset::SystemError(err.str());
}
int heartbeatTime = conf->getArgPInt("--" + argprefix + "heartbeat-time",it.getProp("heartbeatTime"),conf->getHeartBeatTime());
if( heartbeatTime>0 )
int heartbeatTime = conf->getArgPInt("--" + argprefix + "heartbeat-time", it.getProp("heartbeatTime"), conf->getHeartBeatTime());
if( heartbeatTime > 0 )
ptHeartBeat.setTiming(heartbeatTime);
else
ptHeartBeat.setTiming(UniSetTimer::WaitUpTime);
maxHeartBeat = conf->getArgPInt("--" + argprefix + "heartbeat-max",it.getProp("heartbeat_max"), 10);
maxHeartBeat = conf->getArgPInt("--" + argprefix + "heartbeat-max", it.getProp("heartbeat_max"), 10);
}
// Инициализация значений
......@@ -188,16 +193,18 @@ end_private(false)
si.id = uniset::DefaultObjectId;
si.node = conf->getLocalNode();
sleep_msec = conf->getArgPInt("--" + argprefix + "sleep-msec","150", 150);
sleep_msec = conf->getArgPInt("--" + argprefix + "sleep-msec", "150", 150);
string s_resetTime("");
if( s_resetTime.empty() ) // -V547
s_resetTime = "500";
resetMsgTime = uni_atoi(init4_str(conf->getArgParam("--" + argprefix + "resetMsgTime"),conf->getProp(cnode,"resetMsgTime"),conf->getProp(globalnode,"resetMsgTime"), s_resetTime));
resetMsgTime = uni_atoi(init4_str(conf->getArgParam("--" + argprefix + "resetMsgTime"), conf->getProp(cnode, "resetMsgTime"), conf->getProp(globalnode, "resetMsgTime"), s_resetTime));
ptResetMsg.setTiming(resetMsgTime);
int sm_tout = conf->getArgInt("--" + argprefix + "sm-ready-timeout","");
int sm_tout = conf->getArgInt("--" + argprefix + "sm-ready-timeout", "");
if( sm_tout == 0 )
smReadyTimeout = conf->getNCReadyTimeout();
else if( sm_tout < 0 )
......@@ -205,7 +212,7 @@ end_private(false)
else
smReadyTimeout = sm_tout;
smTestID = conf->getSensorID(init4_str(conf->getArgParam("--" + argprefix + "sm-test-id"),conf->getProp(cnode,"smTestID"),conf->getProp(globalnode,"smTestID"),""));
smTestID = conf->getSensorID(init4_str(conf->getArgParam("--" + argprefix + "sm-test-id"), conf->getProp(cnode, "smTestID"), conf->getProp(globalnode, "smTestID"), ""));
if( smTestID == DefaultObjectId ) // -V547
......@@ -232,7 +239,7 @@ end_private(false)
// help надо выводить в конце, когда уже все переменные инициализированы по умолчанию
if( uniset::findArgParam("--" + argprefix + "help",uniset_conf()->getArgc(),uniset_conf()->getArgv()) != -1 )
if( uniset::findArgParam("--" + argprefix + "help", uniset_conf()->getArgc(), uniset_conf()->getArgv()) != -1 )
cout << help() << endl;
}
......@@ -284,7 +291,7 @@ bool UObject_SK::setMsg( uniset::ObjectId _code, bool _state ) noexcept
void UObject_SK::resetMsg()
{
mylog8 << myname << "(resetMsg): reset messages.." << endl;
// reset messages
// reset messages
}
// -----------------------------------------------------------------------------
......@@ -313,11 +320,11 @@ Poco::JSON::Object::Ptr UObject_SK::httpDumpIO()
{
Poco::JSON::Object::Ptr jdata = new Poco::JSON::Object();
Poco::JSON::Object::Ptr j_in = uniset::json::make_child(jdata,"in");
Poco::JSON::Object::Ptr j_in = uniset::json::make_child(jdata, "in");
Poco::JSON::Object::Ptr j_out = uniset::json::make_child(jdata,"out");
Poco::JSON::Object::Ptr j_out = uniset::json::make_child(jdata, "out");
......@@ -342,19 +349,23 @@ std::string UObject_SK::dumpIO()
s << endl;
int n = 0;
for( const auto& e: v_in )
for( const auto& e : v_in )
{
s << e;
if( (n++)%2 )
if( (n++) % 2 )
s << std::endl;
}
s << endl;
n = 0;
for( const auto& e: v_out )
for( const auto& e : v_out )
{
s << e;
if( (n++)%2 )
if( (n++) % 2 )
s << std::endl;
}
......@@ -441,14 +452,17 @@ void UObject_SK::preSysCommand( const SystemMessage* _sm )
{
case SystemMessage::WatchDog:
myinfo << myname << "(preSysCommand): WatchDog" << endl;
if( !active || !ptStartUpTimeout.checkTime() )
{
mywarn << myname << "(preSysCommand): игнорируем WatchDog, потому-что только-что стартанули" << endl;
break;
}
case SystemMessage::StartUp:
{
ostate = "StartUp...";
try
{
if( !logserv_host.empty() && logserv_port != 0 && !logserv->isRunning() )
......@@ -468,10 +482,12 @@ void UObject_SK::preSysCommand( const SystemMessage* _sm )
}
ostate = "StartUp: wait sm ready..";
if( !waitSM(smReadyTimeout) )
{
if( !cancelled )
uterminate();
return;
}
......@@ -504,10 +520,11 @@ void UObject_SK::preSysCommand( const SystemMessage* _sm )
// переоткрываем логи
mylogany << myname << "(preSysCommand): logRotate" << endl;
string fname( log()->getLogFile() );
if( !fname.empty() )
{
mylog->logFile(fname.c_str(),false);
mylog->logFile(fname.c_str(), false);
mylogany << myname << "(preSysCommand): ***************** mylog LOG ROTATE *****************" << endl;
}
......@@ -563,8 +580,10 @@ uniset::SimpleInfo* UObject_SK::getInfo( const char* userparam )
inf << "statistics: " << endl
<< " processingMessageCatchCount: " << processingMessageCatchCount << endl;
inf << " Type of messages: " << endl;
for( const auto& s: msgTypeStat )
for( const auto& s : msgTypeStat )
inf << " (" << s.first << ")" << setw(10) << getTypeOfMessage(s.first) << ": " << setw(5) << s.second << endl;
inf << endl;
......@@ -572,14 +591,16 @@ uniset::SimpleInfo* UObject_SK::getInfo( const char* userparam )
inf << endl;
auto timers = getTimersList();
inf << "Timers[" << timers.size() << "]:" << endl;
for( const auto& t: timers )
for( const auto& t : timers )
{
inf << " " << setw(15) << getTimerName(t.id) << "[" << t.id << "]: msec="
<< setw(6) << t.tmr.getInterval()
<< " timeleft=" << setw(6) << t.curTimeMS
<< " tick=" << setw(3) << ( t.curTick>=0 ? t.curTick : -1 )
<< " tick=" << setw(3) << ( t.curTick >= 0 ? t.curTick : -1 )
<< endl;
}
inf << endl;
inf << vmon.pretty_str() << endl;
inf << endl;
......@@ -597,49 +618,53 @@ Poco::JSON::Object::Ptr UObject_SK::httpGet( const Poco::URI::QueryParameters& p
Poco::JSON::Object::Ptr json = UniSetObject::httpGet(params);
Poco::JSON::Object::Ptr jdata = json->getObject(myname);
if( !jdata )
jdata = uniset::json::make_child(json,myname);
jdata = uniset::json::make_child(json, myname);
Poco::JSON::Object::Ptr jserv = uniset::json::make_child(jdata, "LogServer");
Poco::JSON::Object::Ptr jserv = uniset::json::make_child(jdata,"LogServer");
if( logserv )
{
jserv->set("host",logserv_host);
jserv->set("port",logserv_port);
jserv->set("state",( logserv->isRunning() ? "RUNNIG" : "STOPPED" ));
jserv->set("host", logserv_host);
jserv->set("port", logserv_port);
jserv->set("state", ( logserv->isRunning() ? "RUNNIG" : "STOPPED" ));
jserv->set("info", logserv->httpGetShortInfo());
}
jdata->set("io", httpDumpIO());
auto timers = getTimersList();
auto jtm = uniset::json::make_child(jdata,"Timers");
auto jtm = uniset::json::make_child(jdata, "Timers");
jtm->set("count", timers.size());
jtm->set("count",timers.size());
for( const auto& t: timers )
for( const auto& t : timers )
{
auto jt = uniset::json::make_child(jtm,to_string(t.id));
auto jt = uniset::json::make_child(jtm, to_string(t.id));
jt->set("id", t.id);
jt->set("name", getTimerName(t.id));
jt->set("msec", t.tmr.getInterval());
jt->set("timeleft", t.curTimeMS);
jt->set("tick", ( t.curTick>=0 ? t.curTick : -1 ));
jt->set("tick", ( t.curTick >= 0 ? t.curTick : -1 ));
}
auto vlist = vmon.getList();
auto jvmon = uniset::json::make_child(jdata,"Variables");
auto jvmon = uniset::json::make_child(jdata, "Variables");
for( const auto& v: vlist )
jvmon->set(v.first,v.second);
for( const auto& v : vlist )
jvmon->set(v.first, v.second);
auto jstat = uniset::json::make_child(jdata,"Statistics");
auto jstat = uniset::json::make_child(jdata, "Statistics");
jstat->set("processingMessageCatchCount", processingMessageCatchCount);
auto jsens = uniset::json::make_child(jstat,"sensors");
for( const auto& s: smStat )
auto jsens = uniset::json::make_child(jstat, "sensors");
for( const auto& s : smStat )
{
std::string sname(ORepHelpers::getShortName( uniset_conf()->oind->getMapName(s.first)));
auto js = uniset::json::make_child(jsens,sname);
auto js = uniset::json::make_child(jsens, sname);
js->set("id", s.first);
js->set("name", sname);
js->set("count", s.second);
......@@ -656,7 +681,7 @@ Poco::JSON::Object::Ptr UObject_SK::httpHelp( const Poco::URI::QueryParameters&
uniset::json::help::object myhelp(myname, UniSetObject::httpGet(params));
// 'log'
uniset::json::help::item cmd("log","show log level");
uniset::json::help::item cmd("log", "show log level");
myhelp.add(cmd);
return myhelp;
......@@ -667,13 +692,13 @@ Poco::JSON::Object::Ptr UObject_SK::httpRequest( const std::string& req, const P
if( req == "log" )
return httpRequestLog(p);
return UniSetObject::httpRequest(req,p);
return UniSetObject::httpRequest(req, p);
}
// -----------------------------------------------------------------------------
Poco::JSON::Object::Ptr UObject_SK::httpRequestLog( const Poco::URI::QueryParameters& p )
{
Poco::JSON::Object::Ptr jret = new Poco::JSON::Object();
jret->set("log",Debug::str(mylog->level()));
jret->set("log", Debug::str(mylog->level()));
return jret;
}
// -----------------------------------------------------------------------------
......@@ -722,7 +747,7 @@ bool UObject_SK::waitSM( int wait_msec, ObjectId _testID )
<< " testID=" << _testID << endl;
// waitReady можно использовать т.к. датчик это по сути IONotifyController
if( !ui->waitReadyWithCancellation(_testID,wait_msec,cancelled) )
if( !ui->waitReadyWithCancellation(_testID, wait_msec, cancelled) )
{
ostringstream err;
err << myname
......@@ -733,7 +758,7 @@ bool UObject_SK::waitSM( int wait_msec, ObjectId _testID )
return false;
}
if( !ui->waitWorking(_testID,wait_msec) )
if( !ui->waitWorking(_testID, wait_msec) )
{
ostringstream err;
err << myname
......@@ -779,39 +804,42 @@ void UObject_SK::callback() noexcept
{
if( !active )
return;
try
{
// проверка таймеров
checkTimers(this);
if( resetMsgTime>0 && trResetMsg.hi(ptResetMsg.checkTime()) )
if( resetMsgTime > 0 && trResetMsg.hi(ptResetMsg.checkTime()) )
{
// cout << myname << ": ********* reset messages *********" << endl;
// cout << myname << ": ********* reset messages *********" << endl;
resetMsg();
}
// обработка сообщений (таймеров и т.п.)
for( unsigned int i=0; i<20; i++ )
for( unsigned int i = 0; i < 20; i++ )
{
auto m = receiveMessage();
if( !m )
break;
processingMessage(m.get());
updateOutputs(forceOut);
// updatePreviousValues();
// updatePreviousValues();
}
// Выполнение шага программы
step();
// "сердцебиение"
if( idHeartBeat!=DefaultObjectId && ptHeartBeat.checkTime() )
if( idHeartBeat != DefaultObjectId && ptHeartBeat.checkTime() )
{
try
{
ui->setValue(idHeartBeat,maxHeartBeat);
ui->setValue(idHeartBeat, maxHeartBeat);
ptHeartBeat.reset();
}
catch( const uniset::Exception& ex )
......@@ -851,7 +879,7 @@ void UObject_SK::setValue( uniset::ObjectId _sid, long _val )
ui->setValue(_sid,_val);
ui->setValue(_sid, _val);
}
// -----------------------------------------------------------------------------
void UObject_SK::updateOutputs( bool _force )
......@@ -873,7 +901,7 @@ void UObject_SK::initFromSM()
// -----------------------------------------------------------------------------
void UObject_SK::askSensor( uniset::ObjectId _sid, UniversalIO::UIOCommand _cmd, uniset::ObjectId _node )
{
ui->askRemoteSensor(_sid,_cmd,_node,getId());
ui->askRemoteSensor(_sid, _cmd, _node, getId());
}
// -----------------------------------------------------------------------------
long UObject_SK::getValue( uniset::ObjectId _sid )
......@@ -895,10 +923,12 @@ long UObject_SK::getValue( uniset::ObjectId _sid )
void UObject_SK::preAskSensors( UniversalIO::UIOCommand _cmd )
{
PassiveTimer ptAct(activateTimeout);
while( !activated && !ptAct.checkTime() )
{
cout << myname << "(preAskSensors): wait activate..." << endl;
msleep(300);
if( activated )
break;
}
......@@ -918,7 +948,7 @@ void UObject_SK::preAskSensors( UniversalIO::UIOCommand _cmd )
{
mycrit << myname << "(preAskSensors): " << ex << endl;
}
catch( const std::exception&ex )
catch( const std::exception& ex )
{
mycrit << myname << "(execute): catch " << ex.what() << endl;
}
......
......@@ -36,7 +36,7 @@ void LostTestProc::sysCommand( const uniset::SystemMessage* sm )
askTimer(tmCheck, checkTime);
// начальная инициализация значений в SM
for( auto && s : slist )
for( auto&& s : slist )
{
try
{
......@@ -79,7 +79,7 @@ void LostTestProc::timerInfo( const TimerMessage* tm )
myinfo << myname << ": [OK]: empty queue. CHECK VALUE... " << endl;
for( auto && s : slist )
for( auto&& s : slist )
{
try
{
......@@ -131,7 +131,7 @@ void LostTestProc::timerInfo( const TimerMessage* tm )
myinfo << myname << ": [OK]: UPDATE VALUE... " << endl;
for( auto && s : slist )
for( auto&& s : slist )
{
try
{
......
......@@ -74,7 +74,7 @@ void run_test(std::size_t concurrency, int bound, shared_ptr<SharedMemory>& shm
for (std::size_t i = 0; i < concurrency / 2 - 1; ++i)
threads.emplace_back(w_worker);
for (auto && thread : threads)
for (auto&& thread : threads)
thread.join();
}
// --------------------------------------------------------------------------
......
......@@ -29,25 +29,17 @@
//------------------------------------------------------------------------------------------
namespace uniset
{
/*!
\page ServicesPage
\section secDBServer Сервис ведения БД
\subsection subDBS_common Общие сведения
/*! Прототип реализации сервиса ведения БД
Предназначен для работы с БД.
Основная задача это - сохранение информации о датчиках, ведение журнала сообщений.
\subsection subDBS_idea Сценарий работы
\par Сценарий работы
На узле, где ведётся БД запускается один экземпляр сервиса. Клиенты могут получить доступ, несколькими способами:
- через NameService
- при помощи UInterface::send()
Сервис является системным, поэтому его идентификатор можно получить при помощи
uniset::Configuration::getDBServer() объекта uniset::conf.
Реализацию см. \ref page_DBServer_MySQL и \ref page_DBServer_SQLite
*/
/*! Прототип реализации сервиса ведения БД */
class DBServer:
public UniSetObject
{
......
......@@ -28,21 +28,21 @@
#include "ujson.h"
#include "DebugStream.h"
// -------------------------------------------------------------------------
/*! \page UHttpServer API
/*! \page UHttpServer HTTP API (базовая реализация)
*
* Формат запроса: /api/version/xxx
*
* Пока поддерживается только метод GET
* Ответ в формате JSON
* В текущем API не подразумеваются запросы глубже '/api/version/ObjectName/xxxx'
*
* Версия API: v01
* /api/version/list - Получение списка доступных объектов
* /api/version/help - Получение списка доступных команд
* /api/version/ObjectName - получение информации об объекте ObjectName
* /api/version/ObjectName/help - получение списка доступных команд для объекта ObjectName
* /api/version/ObjectName/xxxx - 'xxx' запрос к объекту ObjectName
* <br>Пока поддерживается только метод GET
* <br>Ответ в формате JSON
* <br>В текущем API не подразумеваются запросы глубже '/api/version/ObjectName/xxxx'
*
* Версия API: \b v01
* - /api/version/list - Получение списка доступных объектов
* - /api/version/help - Получение списка доступных команд
* - /api/version/ObjectName - получение информации об объекте ObjectName
* - /api/version/ObjectName/help - получение списка доступных команд для объекта ObjectName
* - /api/version/ObjectName/xxxx - 'xxx' запрос к объекту ObjectName
*\code
* HELP FORMAT:
* myname {
* help [
......@@ -65,7 +65,7 @@
* ...
* ]
* }
*
*\endcode
*
* \todo подумать над /api/version/tree - получение "дерева" объектов (древовидный список с учётом подчинения Manager/Objects)
*/
......
......@@ -55,7 +55,7 @@ namespace uniset
fnFileTransfer = 0x66 /*!< file transfer */
};
/*! Коды диагностически подфункций (для запроса 0x08) */
/*! Коды диагностических подфункций (для запроса 0x08) */
enum DiagnosticsSubFunction
{
subEcho = 0x00, /*!< (0) Return Query Data (echo) */
......
......@@ -273,7 +273,7 @@ bool UProxyObject_impl::impl_updateValues()
std::unique_lock<std::mutex> lk(mutexSMap);
bool ret = true;
for( auto && i : smap )
for( auto&& i : smap )
{
try
{
......
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