Skip to content
Snippets Groups Projects
Commit eec498b9 authored by ziemke's avatar ziemke
Browse files

Task #1703: Added new get and set_datapoint methods to handle int vectors and...

Task #1703: Added new get and set_datapoint methods to handle int vectors and python boost lists and tuples. Fixed bugs in pywincc python bindings
parent ac47a4e5
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,8 @@ include(LofarFindPackage) ...@@ -6,6 +6,8 @@ include(LofarFindPackage)
#hard-coded path where wincc api can be found on build systems #hard-coded path where wincc api can be found on build systems
set(WINCC_ROOT_DIR /opt/WinCC_OA/3.15 CACHE PATH "root dir where the WinCC_OA api can be found") set(WINCC_ROOT_DIR /opt/WinCC_OA/3.15 CACHE PATH "root dir where the WinCC_OA api can be found")
lofar_find_package(WINCC) lofar_find_package(WINCC)
lofar_find_package(Boost REQUIRED python)
lofar_find_package(Python)
IF(WINCC_FOUND) IF(WINCC_FOUND)
add_subdirectory(include) add_subdirectory(include)
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <Manager.hxx> #include <Manager.hxx>
#include <Variable.hxx> #include <Variable.hxx>
#include <boost/python.hpp>
namespace LOFAR { namespace LOFAR {
namespace WINCCWRAPPER { namespace WINCCWRAPPER {
...@@ -69,12 +71,11 @@ public: ...@@ -69,12 +71,11 @@ public:
bool get_datapoint(const std::string &name, std::string &value); bool get_datapoint(const std::string &name, std::string &value);
//! get the datapoint with the given name and return it's tm value in parameter value. returns true upon success. //! get the datapoint with the given name and return it's tm value in parameter value. returns true upon success.
bool get_datapoint(const std::string &name, struct tm &value); bool get_datapoint(const std::string &name, struct tm &value);
//! get the datapoint with the given name and return it's DynVar value in parameter value. returns true upon success. //! get the datapoint with the given name and return it's boost::python::list value in parameter value. returns true upon success.
bool get_datapoint(const std::string &name, int value[]); bool get_datapoint(const std::string &name, boost::python::list &value);
//! get the datapoint with the given name and return it's std::vector<int> value in parameter value. returns true upon success.
bool get_datapoint(const std::string &name, std::vector<int> &value); bool get_datapoint(const std::string &name, std::vector<int> &value);
//! mark the datapoint with given name valid. returns true upon success. //! mark the datapoint with given name valid. returns true upon success.
bool set_datapoint_valid(const std::string &name) { return set_datapoint_validity(name, true, nullptr); } bool set_datapoint_valid(const std::string &name) { return set_datapoint_validity(name, true, nullptr); }
//! mark the datapoint with given name invalid. returns true upon success. //! mark the datapoint with given name invalid. returns true upon success.
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include "WinCCResources.h" #include "WinCCResources.h"
#include "WinCCManager.h" #include "WinCCManager.h"
#include <boost/python.hpp>
namespace LOFAR { namespace LOFAR {
namespace WINCCWRAPPER { namespace WINCCWRAPPER {
...@@ -50,8 +52,13 @@ public: ...@@ -50,8 +52,13 @@ public:
//! set the datapoint with given name to the given int value, mark it valid/invalid, returns true upon success. //! set the datapoint with given name to the given int value, mark it valid/invalid, returns true upon success.
bool set_datapoint(const std::string &name, int value, bool valid=true); bool set_datapoint(const std::string &name, int value, bool valid=true);
//! set the datapoint with given name to the given boost::python::list value, mark it valid/invalid, returns true upon success.
bool set_datapoint(const std::string &name, boost::python::list &value, bool valid=true);
//! set the datapoint with given name to the given boost::python::tuple value, mark it valid/invalid, returns true upon success.
bool set_datapoint(const std::string &name, boost::python::tuple &value, bool valid=true);
//! set the datapoint with given name to the given std::vector<int> value, mark it valid/invalid, returns true upon success. //! set the datapoint with given name to the given std::vector<int> value, mark it valid/invalid, returns true upon success.
bool set_datapoint(const std::string &name, std::vector<int> &value, bool valid=true); bool set_datapoint(const std::string &name, std::vector<int> &value, bool valid=true);
//! set the datapoint with given name to the given long value, mark it valid/invalid, returns true upon success. //! set the datapoint with given name to the given long value, mark it valid/invalid, returns true upon success.
bool set_datapoint(const std::string &name, long value, bool valid=true); bool set_datapoint(const std::string &name, long value, bool valid=true);
//! set the datapoint with given name to the given float value, mark it valid/invalid, returns true upon success. //! set the datapoint with given name to the given float value, mark it valid/invalid, returns true upon success.
...@@ -80,8 +87,11 @@ public: ...@@ -80,8 +87,11 @@ public:
std::string get_datapoint_string(const std::string &name); std::string get_datapoint_string(const std::string &name);
//! get the datapoint with the given name and return it as a time_t value if possible, otherwise an exception is raised. //! get the datapoint with the given name and return it as a time_t value if possible, otherwise an exception is raised.
time_t get_datapoint_time(const std::string &name); time_t get_datapoint_time(const std::string &name);
//! get the datapoint with the given name and return it as a boost::python::list value if possible, otherwise an exception is raised.
boost::python::list get_datapoint_list(const std::string &name);
//! get the datapoint with the given name and return it as a std::vector<int> value if possible, otherwise an exception is raised. //! get the datapoint with the given name and return it as a std::vector<int> value if possible, otherwise an exception is raised.
std::vector<int> get_datapoint_int_vector(const std::string &name); //! this method is used in the WinCCGet test
std::vector<int> get_datapoint_vector(const std::string &name);
private: private:
// get_datapoint // get_datapoint
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <DynPtrArray.hxx> #include <DynPtrArray.hxx>
#include <cassert> #include <cassert>
#include <vector> #include <vector>
#include <boost/python.hpp>
namespace LOFAR { namespace LOFAR {
namespace WINCCWRAPPER { namespace WINCCWRAPPER {
...@@ -228,6 +229,27 @@ bool WinCCManager::get_datapoint_variable(const std::string &name, Variable *&va ...@@ -228,6 +229,27 @@ bool WinCCManager::get_datapoint_variable(const std::string &name, Variable *&va
template <typename Tval> template <typename Tval>
Variable::ConvertResult convert(Variable *var, Tval &value, Variable *&converted_var); Variable::ConvertResult convert(Variable *var, Tval &value, Variable *&converted_var);
template <>
Variable::ConvertResult convert(Variable *var, boost::python::list& value, Variable *&converted_var)
{
Variable::ConvertResult cr = var->convert(VariableType::DYNINTEGER_VAR, converted_var);
if(Variable::ConvertResult::OK == cr)
{
DynVar *dv = (DynVar*)converted_var;
for(unsigned int i = 0; i < dv->getNumberOfItems(); i++) {
Variable *elem = dv->getAt(i);
if(elem->inherits(VariableType::INTEGER_VAR)) {
value.append(((IntegerVar*)elem)->getValue());
}
else
return Variable::ConvertResult::CONV_NOT_DEFINED;
}
}
return cr;
}
template <> template <>
Variable::ConvertResult convert(Variable *var, std::vector<int> &value, Variable *&converted_var) Variable::ConvertResult convert(Variable *var, std::vector<int> &value, Variable *&converted_var)
{ {
...@@ -369,6 +391,11 @@ bool WinCCManager::get_datapoint(const std::string &name, struct tm &value) ...@@ -369,6 +391,11 @@ bool WinCCManager::get_datapoint(const std::string &name, struct tm &value)
return _get_datapoint(name, value); return _get_datapoint(name, value);
} }
bool WinCCManager::get_datapoint(const std::string &name, boost::python::list &value)
{
return _get_datapoint(name, value);
}
bool WinCCManager::get_datapoint(const std::string &name, std::vector<int> &value) bool WinCCManager::get_datapoint(const std::string &name, std::vector<int> &value)
{ {
return _get_datapoint(name, value); return _get_datapoint(name, value);
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <LongVar.hxx> #include <LongVar.hxx>
#include <TimeVar.hxx> #include <TimeVar.hxx>
#include <DynVar.hxx> #include <DynVar.hxx>
#include <vector>
#include <Variable.hxx> #include <Variable.hxx>
#include <condition_variable> #include <condition_variable>
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include "WinCCWrapper.h" #include "WinCCWrapper.h"
#include "ConnectWaitForAnswer.h" #include "ConnectWaitForAnswer.h"
#include <boost/python.hpp>
namespace LOFAR { namespace LOFAR {
namespace WINCCWRAPPER { namespace WINCCWRAPPER {
...@@ -76,6 +78,24 @@ bool WinCCWrapper::set_datapoint(const std::string &name, int value, bool valid) ...@@ -76,6 +78,24 @@ bool WinCCWrapper::set_datapoint(const std::string &name, int value, bool valid)
return manager->set_datapoint(name + DP_SUFFIX, variable, valid); return manager->set_datapoint(name + DP_SUFFIX, variable, valid);
} }
bool WinCCWrapper::set_datapoint(const std::string &name, boost::python::list &value, bool valid)
{
DynVar variable(VariableType::INTEGER_VAR);
for(int i = 0; i < boost::python::len(value); i++) {
int boost_elem = boost::python::extract<int>(value[i]);
IntegerVar elem{boost_elem};
variable.append(elem);}
return manager->set_datapoint(name + DP_SUFFIX, variable, valid);
}
bool WinCCWrapper::set_datapoint(const std::string &name, boost::python::tuple &value, bool valid)
{
// do a simple type conversion to a boost::python::list to access the 'append' method
boost::python::list temp_list = boost::python::list(value);
return set_datapoint(name, temp_list, valid);
}
bool WinCCWrapper::set_datapoint(const std::string &name, std::vector<int> &value, bool valid) bool WinCCWrapper::set_datapoint(const std::string &name, std::vector<int> &value, bool valid)
{ {
DynVar variable(VariableType::INTEGER_VAR); DynVar variable(VariableType::INTEGER_VAR);
...@@ -137,7 +157,15 @@ int WinCCWrapper::get_datapoint_int(const std::string &name) ...@@ -137,7 +157,15 @@ int WinCCWrapper::get_datapoint_int(const std::string &name)
throw std::runtime_error("Could not get datapoint"); throw std::runtime_error("Could not get datapoint");
} }
std::vector<int> WinCCWrapper::get_datapoint_int_vector(const std::string &name) boost::python::list WinCCWrapper::get_datapoint_list(const std::string &name)
{
boost::python::list value;
if(get_datapoint(name, value))
return value;
throw std::runtime_error("Could not get datapoint");
}
std::vector<int> WinCCWrapper::get_datapoint_vector(const std::string &name)
{ {
std::vector<int> value; std::vector<int> value;
if(get_datapoint(name, value)) if(get_datapoint(name, value))
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
//# The LOFAR Software Suite is free software: you can redistribute it and/or //# The LOFAR Software Suite is free software: you can redistribute it and/or
//# modify it under the terms of the GNU General Public License as published by //# modify it under the terms of the GNU General Public License as published by
//# the Free Software Foundation, either version 3 of the License, or (at your //# the Free Software Foundation, either version 3 of the License, or (at your
//# option) any later version. //# option) any later versions
//# //#
//# The LOFAR Software Suite is distributed in the hope that it will be //# The LOFAR Software Suite is distributed in the hope that it will be
//# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of //# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <boost/python.hpp> #include <boost/python.hpp>
#include "WinCCWrapper.h" #include "WinCCWrapper.h"
#include <vector>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
BOOST_PYTHON_MODULE(pywincc) BOOST_PYTHON_MODULE(pywincc)
{ {
...@@ -26,7 +28,10 @@ BOOST_PYTHON_MODULE(pywincc) ...@@ -26,7 +28,10 @@ BOOST_PYTHON_MODULE(pywincc)
using namespace LOFAR::WINCCWRAPPER; using namespace LOFAR::WINCCWRAPPER;
bool (WinCCWrapper::*set_datapoint_int)(const std::string&, int, bool) = &WinCCWrapper::set_datapoint; bool (WinCCWrapper::*set_datapoint_int)(const std::string&, int, bool) = &WinCCWrapper::set_datapoint;
bool (WinCCWrapper::*set_datapoint_int_vector)(const std::string&, std::vector<int>&, bool) = &WinCCWrapper::set_datapoint; bool (WinCCWrapper::*set_datapoint_list)(const std::string&, boost::python::list&, bool) = &WinCCWrapper::set_datapoint;
bool (WinCCWrapper::*set_datapoint_tuple)(const std::string&, boost::python::tuple&, bool) = &WinCCWrapper::set_datapoint;
// the set_datapoint_vector method is used in the WinCCGet and WinCCSet tests
bool (WinCCWrapper::*set_datapoint_vector)(const std::string&, std::vector<int>&, bool) = &WinCCWrapper::set_datapoint;
bool (WinCCWrapper::*set_datapoint_long)(const std::string&, long, bool) = &WinCCWrapper::set_datapoint; bool (WinCCWrapper::*set_datapoint_long)(const std::string&, long, bool) = &WinCCWrapper::set_datapoint;
bool (WinCCWrapper::*set_datapoint_float)(const std::string&, float, bool) = &WinCCWrapper::set_datapoint; bool (WinCCWrapper::*set_datapoint_float)(const std::string&, float, bool) = &WinCCWrapper::set_datapoint;
bool (WinCCWrapper::*set_datapoint_bool)(const std::string&, bool, bool) = &WinCCWrapper::set_datapoint; bool (WinCCWrapper::*set_datapoint_bool)(const std::string&, bool, bool) = &WinCCWrapper::set_datapoint;
...@@ -35,9 +40,17 @@ BOOST_PYTHON_MODULE(pywincc) ...@@ -35,9 +40,17 @@ BOOST_PYTHON_MODULE(pywincc)
bool (WinCCWrapper::*set_datapoint_valid)(const std::string&) = &WinCCWrapper::set_datapoint_valid; bool (WinCCWrapper::*set_datapoint_valid)(const std::string&) = &WinCCWrapper::set_datapoint_valid;
bool (WinCCWrapper::*set_datapoint_invalid)(const std::string&) = &WinCCWrapper::set_datapoint_invalid; bool (WinCCWrapper::*set_datapoint_invalid)(const std::string&) = &WinCCWrapper::set_datapoint_invalid;
// define the conversion between std::vector<int> and boost::python::list
class_<std::vector<int>>("VectorIterable")
.def(vector_indexing_suite<std::vector<int>>())
;
class_<WinCCWrapper>("WinCCWrapper", init<const std::string&>()) class_<WinCCWrapper>("WinCCWrapper", init<const std::string&>())
.def("set_datapoint_int", set_datapoint_int) .def("set_datapoint_int", set_datapoint_int)
.def("set_datapoint_int_vector", set_datapoint_int_vector) .def("set_datapoint_list", set_datapoint_list)
// define the "set_datapoint_list" method once more to accept a tuple instead of a list
.def("set_datapoint_list", set_datapoint_tuple)
.def("set_datapoint_vector", set_datapoint_vector)
.def("set_datapoint_long", set_datapoint_long) .def("set_datapoint_long", set_datapoint_long)
.def("set_datapoint_float", set_datapoint_float) .def("set_datapoint_float", set_datapoint_float)
.def("set_datapoint_bool", set_datapoint_bool) .def("set_datapoint_bool", set_datapoint_bool)
...@@ -47,7 +60,8 @@ BOOST_PYTHON_MODULE(pywincc) ...@@ -47,7 +60,8 @@ BOOST_PYTHON_MODULE(pywincc)
.def("set_datapoint_valid", set_datapoint_valid) .def("set_datapoint_valid", set_datapoint_valid)
.def("set_datapoint_invalid", set_datapoint_invalid) .def("set_datapoint_invalid", set_datapoint_invalid)
.def("get_datapoint_int", &WinCCWrapper::get_datapoint_int) .def("get_datapoint_int", &WinCCWrapper::get_datapoint_int)
.def("get_datapoint_int_vector", &WinCCWrapper::get_datapoint_int_vector) .def("get_datapoint_list", &WinCCWrapper::get_datapoint_list)
.def("get_datapoint_vector", &WinCCWrapper::get_datapoint_vector)
.def("get_datapoint_long", &WinCCWrapper::get_datapoint_long) .def("get_datapoint_long", &WinCCWrapper::get_datapoint_long)
.def("get_datapoint_float", &WinCCWrapper::get_datapoint_float) .def("get_datapoint_float", &WinCCWrapper::get_datapoint_float)
.def("get_datapoint_bool", &WinCCWrapper::get_datapoint_bool) .def("get_datapoint_bool", &WinCCWrapper::get_datapoint_bool)
......
...@@ -4,5 +4,19 @@ IF(BUILD_TESTING) ...@@ -4,5 +4,19 @@ IF(BUILD_TESTING)
lofar_add_bin_program(WinCCSet WinCCSet.cc) lofar_add_bin_program(WinCCSet WinCCSet.cc)
lofar_add_bin_program(WinCCGet WinCCGet.cc) lofar_add_bin_program(WinCCGet WinCCGet.cc)
# Start of added material
# Try to find Boost-Python.
# If found, build the bindings, otherwise give a warning.
FIND_PATH(BOOST_PYTHON_FOUND "boost/python.hpp")
# create python modules and boost python bindings
include(LofarFindPackage)
lofar_find_package(Python 2.6 REQUIRED)
lofar_find_package(Boost REQUIRED COMPONENTS python)
# End of added material
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
ENDIF(BUILD_TESTING) ENDIF(BUILD_TESTING)
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
#include <string> #include <string>
#include <WinCCWrapper.h> #include <WinCCWrapper.h>
#include <vector> #include <vector>
#include <boost/python.hpp>
#include <iostream>
#include <boost/format.hpp>
using namespace LOFAR::WINCCWRAPPER; using namespace LOFAR::WINCCWRAPPER;
using namespace std; using namespace std;
...@@ -41,16 +44,17 @@ int main(int argc, char * argv[]) ...@@ -41,16 +44,17 @@ int main(int argc, char * argv[])
value = wrapper.get_datapoint_string(dpname); value = wrapper.get_datapoint_string(dpname);
cout << dpname << ": " << value << endl; cout << dpname << ": " << value << endl;
} }
else if (string(argv[2]) == "vector") { else if (string(argv[2]) == "list") {
vector<int> value; // We use the argument 'list' for consistency with the python interface,
value = wrapper.get_datapoint_int_vector(dpname); // even though we must pass a vector
std::vector<int> value;
cout << dpname << ": "; value = wrapper.get_datapoint_vector(dpname);
cout << dpname << ": [";
for (auto iter = value.cbegin(); iter != value.cend(); iter++) { for (auto iter = value.cbegin(); iter != value.cend(); iter++) {
cout << *iter << " "; cout << *iter << ", ";
} }
cout << endl; cout << "\b\b]" << endl; // remove the last ', ' from the end.
} }
else { else {
cout << "Unknown datatype: " << string(argv[2]) << "\n" << endl; cout << "Unknown datatype: " << string(argv[2]) << "\n" << endl;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include <string> #include <string>
#include <WinCCWrapper.h> #include <WinCCWrapper.h>
#include <vector> #include <vector>
#include <boost/python.hpp>
using namespace LOFAR::WINCCWRAPPER; using namespace LOFAR::WINCCWRAPPER;
using namespace std; using namespace std;
...@@ -10,7 +11,7 @@ void get_help(){ ...@@ -10,7 +11,7 @@ void get_help(){
cout << "Usage:" << endl; cout << "Usage:" << endl;
cout << "WinCCSet \"datapoint_name\" datapoint_type new_value" << endl; cout << "WinCCSet \"datapoint_name\" datapoint_type new_value" << endl;
cout << "Accepted datapoint types:" << endl; cout << "Accepted datapoint types:" << endl;
cout << " int, float, string, vector (for int vectors)" << endl; cout << " int, float, string, list (for int list)" << endl;
} }
int main(int argc, char * argv[]) int main(int argc, char * argv[])
...@@ -22,7 +23,6 @@ int main(int argc, char * argv[]) ...@@ -22,7 +23,6 @@ int main(int argc, char * argv[])
get_help(); get_help();
return 0; return 0;
} }
WinCCWrapper wrapper{""}; WinCCWrapper wrapper{""};
string dpname{argv[1]}; string dpname{argv[1]};
...@@ -38,8 +38,10 @@ int main(int argc, char * argv[]) ...@@ -38,8 +38,10 @@ int main(int argc, char * argv[])
string value{argv[3]}; string value{argv[3]};
wrapper.set_datapoint(dpname, value); wrapper.set_datapoint(dpname, value);
} }
else if (string(argv[2]) == "vector") { else if (string(argv[2]) == "list") {
// we cannot append to lists made outside of a boost python module declaration,
// so we pass a vector instead.
// We use the argument "list" for consistency with the python interface
vector<int> value(argc-3); vector<int> value(argc-3);
for (int i = 3; i < argc; i++) { for (int i = 3; i < argc; i++) {
...@@ -54,3 +56,4 @@ int main(int argc, char * argv[]) ...@@ -54,3 +56,4 @@ int main(int argc, char * argv[])
} }
return 0; return 0;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment