Commit 575ce067 authored by Pavel Vainerman's avatar Pavel Vainerman

(python): Добавил реализацию UProxyObject. Объект асинхронно (поток),

следащий за датчиками и предоставляющий интерфейс для получения значения.
parent f90f053d
......@@ -17,14 +17,17 @@ pyUExceptions.py: _pyUExceptions.la
pyexec_LTLIBRARIES = _pyUConnector.la _pyUModbus.la _pyUExceptions.la _pyUniSet.la
_pyUniSet_la_SOURCES = PyUInterface.cc UInterface_wrap.cxx
_pyUniSet_la_CXXFLAGS = $(UNISET_CFLAGS) $(PYTHON_CFLAGS)
_pyUniSet_la_SOURCES = PyUInterface.cc UInterface_wrap.cxx UProxyObject.cc
_pyUniSet_la_CXXFLAGS = $(UNISET_CFLAGS) $(UNISET_EXT_CFLAGS) $(PYTHON_CFLAGS)
_pyUniSet_la_LDFLAGS = -module -avoid-version
_pyUniSet_la_LIBADD = $(UNISET_LIBS) $(PYTHON_LIBS)
_pyUniSet_la_LIBADD = $(UNISET_LIBS) $(UNISET_EXT_LIBS) $(PYTHON_LIBS)
UInterface_wrap.cxx: UInterface.i PyUInterface.h
UInterface_wrap.cxx: UInterface.i UProxyObject.i PyUInterface.h UProxyObject.h
swig -python -c++ -classic UInterface.i
#PyUObject_wrap.cxx: UObject.i PyUObject.h
# swig -python -c++ -classic UObject.i
_pyUConnector_la_SOURCES = UConnector.cc UConnector_wrap.cxx
_pyUConnector_la_CXXFLAGS = $(UNISET_CFLAGS) $(PYTHON_CFLAGS)
_pyUConnector_la_LDFLAGS = -module -avoid-version
......@@ -33,6 +36,7 @@ _pyUConnector_la_LIBADD = $(UNISET_LIBS) $(PYTHON_LIBS)
UConnector_wrap.cxx: UConnector.i UConnector.h
swig -python -c++ -classic UConnector.i
_pyUModbus_la_SOURCES = UModbus.cc UModbus_wrap.cxx
_pyUModbus_la_CXXFLAGS = $(UNISET_CFLAGS) $(UNISET_EXT_CFLAGS) $(POCO_CFLAGS) $(PYTHON_CFLAGS)
_pyUModbus_la_LDFLAGS = -module -avoid-version
......
......@@ -19,6 +19,7 @@
#include "ORepHelpers.h"
#include "UInterface.h"
#include "Configuration.h"
#include "UniSetActivator.h"
#include "UniSetTypes.h"
#include "PyUInterface.h"
//---------------------------------------------------------------------------
......@@ -195,3 +196,17 @@ string pyUInterface::getConfFileName()
}
//---------------------------------------------------------------------------
void pyUInterface::uniset_activate_objects()throw(UException)
{
try
{
auto act = UniSetActivator::Instance();
act->run(true);
}
catch( const std::exception& ex )
{
throw UException("(uniset_activate_objects): catch " + std::string(ex.what()) );
}
}
//---------------------------------------------------------------------------
......@@ -25,6 +25,7 @@ namespace pyUInterface
{
void uniset_init_params( UTypes::Params* p, const std::string& xmlfile )throw(UException);
void uniset_init( int argc, char** argv, const std::string& xmlfile )throw(UException);
void uniset_activate_objects() throw(UException);
//---------------------------------------------------------------------------
long getValue( long id )throw(UException);
......
......@@ -10,9 +10,11 @@
%{
#include "PyUInterface.h"
#include "UProxyObject.h"
%}
/* Для генерации классов и констант в Питоне */
%include "PyUInterface.h"
%include "UTypes.h"
%include "UExceptions.h"
%include "UProxyObject.h"
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// --------------------------------------------------------------------------
#include <sstream>
#include <mutex>
#include <string>
#include <unordered_map>
#include "Configuration.h"
#include "extensions/UObject_SK.h"
#include "UniSetActivator.h"
#include "UProxyObject.h"
// --------------------------------------------------------------------------
using namespace UniSetTypes;
// --------------------------------------------------------------------------
/*! PIMPL реализация UProxyObject */
class UProxyObject_impl:
public UObject_SK
{
public:
UProxyObject_impl( UniSetTypes::ObjectId id );
virtual ~UProxyObject_impl();
void impl_addToAsk( UniSetTypes::ObjectId id ) throw(UException);
long impl_getValue( long id ) throw(UException);
void impl_setValue( long id, long val ) throw(UException);
float impl_getFloatValue( long id ) throw(UException);
protected:
virtual void askSensors( UniversalIO::UIOCommand cmd ) override;
virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override;
private:
struct SInfo
{
IOController_i::SensorInfo si;
long value = { 0 };
float fvalue = { 0.0 };
};
std::mutex mutexSMap;
std::unordered_map<UniSetTypes::ObjectId,SInfo> smap;
};
// --------------------------------------------------------------------------
UProxyObject::UProxyObject() throw(UException)
{
throw UException("(UProxyObject): Unknown 'name'' or 'ID'");
}
// --------------------------------------------------------------------------
UProxyObject::UProxyObject( const std::string& name ) throw( UException ):
UProxyObject::UProxyObject(uniset_conf()->getObjectID(name))
{
}
// --------------------------------------------------------------------------
UProxyObject::UProxyObject( long id ) throw( UException )
{
try
{
uobj = std::make_shared<UProxyObject_impl>(id);
auto act = UniSetActivator::Instance();
act->add(uobj);
}
catch( std::exception& ex )
{
std::ostringstream err;
err << "(UProxyObject): id='" << id << "' error: " << std::string(ex.what());
throw UException(err.str());
}
}
// --------------------------------------------------------------------------
UProxyObject::~UProxyObject()
{
}
// --------------------------------------------------------------------------
long UProxyObject::getValue( long id ) throw(UException)
{
return uobj->impl_getValue(id);
}
// --------------------------------------------------------------------------
void UProxyObject::setValue( long id, long val ) throw(UException)
{
uobj->impl_setValue(id,val);
}
// --------------------------------------------------------------------------
float UProxyObject::getFloatValue( long id ) throw(UException)
{
return uobj->impl_getFloatValue(id);
}
// --------------------------------------------------------------------------
void UProxyObject::addToAsk( long id ) throw(UException)
{
try
{
uobj->impl_addToAsk(id);
}
catch( std::exception& ex )
{
std::ostringstream err;
err << uobj->getName() << "(addToAsk): " << id << " error: " << std::string(ex.what());
throw UException(err.str());
}
}
// --------------------------------------------------------------------------
UProxyObject_impl::UProxyObject_impl( ObjectId id ):
UObject_SK(id)
{
}
// --------------------------------------------------------------------------
UProxyObject_impl::~UProxyObject_impl()
{
}
// --------------------------------------------------------------------------
void UProxyObject_impl::impl_addToAsk( ObjectId id ) throw( UException )
{
UProxyObject_impl::SInfo i;
i.si.id = id;
i.si.node = uniset_conf()->getLocalNode();
std::unique_lock<std::mutex> lk(mutexSMap);
smap[id] = i;
}
// --------------------------------------------------------------------------
long UProxyObject_impl::impl_getValue( long id ) throw(UException)
{
std::unique_lock<std::mutex> lk(mutexSMap);
auto i = smap.find(id);
if( i == smap.end() )
{
std::ostringstream err;
err << myname << "(getValue): " << id << " not found in proxy sensors list..";
throw UException(err.str());
}
return i->second.value;
}
// --------------------------------------------------------------------------
float UProxyObject_impl::impl_getFloatValue( long id ) throw(UException)
{
std::unique_lock<std::mutex> lk(mutexSMap);
auto i = smap.find(id);
if( i == smap.end() )
{
std::ostringstream err;
err << myname << "(getFloatValue): " << id << " not found in proxy sensors list..";
throw UException(err.str());
}
return i->second.fvalue;
}
// --------------------------------------------------------------------------
void UProxyObject_impl::impl_setValue( long id, long val ) throw(UException)
{
try
{
UObject_SK::setValue(id,val);
}
catch( std::exception& ex )
{
std::ostringstream err;
err << myname << "(setValue): " << id << " error: " << std::string(ex.what());
throw UException(err.str());
}
}
// --------------------------------------------------------------------------
void UProxyObject_impl::askSensors( UniversalIO::UIOCommand cmd )
{
std::unique_lock<std::mutex> lk(mutexSMap);
for( const auto& i: smap )
{
try
{
ui->askRemoteSensor(i.second.si.id,cmd,i.second.si.node, getId());
}
catch( std::exception& ex )
{
std::ostringstream err;
err << myname << "(askSensors): " << i.second.si.id << " error: " << std::string(ex.what());
throw UException(err.str());
}
}
}
// --------------------------------------------------------------------------
void UProxyObject_impl::sensorInfo( const SensorMessage* sm )
{
std::unique_lock<std::mutex> lk(mutexSMap);
auto i = smap.find(sm->id);
if( i != smap.end() )
{
i->second.value = sm->value;
i->second.fvalue = (float)sm->value / pow(10.0, sm->ci.precision);
}
}
// --------------------------------------------------------------------------
/*
* Copyright (c) 2015 Pavel Vainerman.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, version 2.1.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// -------------------------------------------------------------------------
#ifndef UProxyObject_H_
#define UProxyObject_H_
// --------------------------------------------------------------------------
#include <memory>
#include "UExceptions.h"
// --------------------------------------------------------------------------
class UProxyObject_impl; // PIMPL
// --------------------------------------------------------------------------
/*! Интерфейс для взаимодействия с SM (с заказом датчиков).
* Текущая версия рассчитана на наличие локальной SM, т.е. в функциях нет аргумента node.
* Соответственно обращение к датчику на другом узле не возможно.
*
* Если всё-таки понадобится - доработаем.
*
* Общее описание:
* Перед активацией объекта необходимо при помощи addToAsk() добавить список датчиков,
* за которыми требуется "следить". После активации ( см. PyUInterface uniset_activate_objects() )
* (в асинхронном режиме!) объект заказывает датчики и сохраняет у себя их состояние.
* При этом "снаружи" можно запросить значение ранее добавленного датчика при помощи фунции getValue().
* Помимо этого можно изменять состояние датчиков (в SM!) при помощи setValue().
* По сути setValue() просто дублирует функциональность PyUInterface::setValue()
*/
class UProxyObject
{
public:
UProxyObject( const std::string& name ) throw(UException);
UProxyObject( long id ) throw(UException);
~UProxyObject();
//! \note Вызывать надо до активации объекта
void addToAsk( long id ) throw(UException);
long getValue( long id ) throw(UException);
float getFloatValue( long id ) throw(UException);
/*! Сохраняемые датчики не требуют добавления при помощи addToAsk ! */
void setValue( long id, long val ) throw(UException);
protected:
private:
UProxyObject()throw(UException);
std::shared_ptr<UProxyObject_impl> uobj;
};
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
/***********************************************************
* Interface file for wrapping test
* to regenerate the wrappers run:
* swig -python UInterface.i
***********************************************************/
%module pyUniSet
%include "std_string.i"
%{
#include "UProxyObject.h"
%}
/* Для генерации классов и констант в Питоне */
%include "UProxyObject.h"
%include "UTypes.h"
%include "UExceptions.h"
......@@ -82,6 +82,10 @@ def uniset_init(argc, argv, xmlfile):
return _pyUniSet.uniset_init(argc, argv, xmlfile)
uniset_init = _pyUniSet.uniset_init
def uniset_activate_objects():
return _pyUniSet.uniset_activate_objects()
uniset_activate_objects = _pyUniSet.uniset_activate_objects
def getValue(id):
return _pyUniSet.getValue(id)
getValue = _pyUniSet.getValue
......@@ -214,6 +218,36 @@ class USysError(UException):
USysError_swigregister = _pyUniSet.USysError_swigregister
USysError_swigregister(USysError)
class UProxyObject:
__swig_setmethods__ = {}
__setattr__ = lambda self, name, value: _swig_setattr(self, UProxyObject, name, value)
__swig_getmethods__ = {}
__getattr__ = lambda self, name: _swig_getattr(self, UProxyObject, name)
__repr__ = _swig_repr
def __init__(self, *args):
this = _pyUniSet.new_UProxyObject(*args)
try:
self.this.append(this)
except Exception:
self.this = this
__swig_destroy__ = _pyUniSet.delete_UProxyObject
__del__ = lambda self: None
def addToAsk(self, id):
return _pyUniSet.UProxyObject_addToAsk(self, id)
def getValue(self, id):
return _pyUniSet.UProxyObject_getValue(self, id)
def getFloatValue(self, id):
return _pyUniSet.UProxyObject_getFloatValue(self, id)
def setValue(self, id, val):
return _pyUniSet.UProxyObject_setValue(self, id, val)
UProxyObject_swigregister = _pyUniSet.UProxyObject_swigregister
UProxyObject_swigregister(UProxyObject)
# This file is compatible with both classic and new-style classes.
......@@ -22,6 +22,8 @@ if __name__ == "__main__":
try:
uniset_init_params( lst, "test.xml");
obj1 = UProxyObject("TestProc")
uniset_activate_objects();
print "getShortName: id=%d name=%s" % (1, getShortName(1))
print " getName: id=%d name=%s" % (1, getName(1))
......
......@@ -339,6 +339,8 @@ python/examples/test.xml
python/lib/pyUniSet/Makefile.am
python/lib/pyUniSet/PyUInterface.cc
python/lib/pyUniSet/PyUInterface.h
python/lib/pyUniSet/UProxyObject.cc
python/lib/pyUniSet/UProxyObject.h
python/lib/pyUniSet/UConnector.cc
python/lib/pyUniSet/UConnector.h
python/lib/pyUniSet/UConnector_wrap.cxx
......
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