diff --git a/LCS/WinCCWrapper/doc/winccwrapper.md b/LCS/WinCCWrapper/doc/winccwrapper.md index 63ac9fbe26e5409dd390e48af0f8053b7c028c94..ea636aaef669fc024cb72c55385839435a53b21f 100644 --- a/LCS/WinCCWrapper/doc/winccwrapper.md +++ b/LCS/WinCCWrapper/doc/winccwrapper.md @@ -1,124 +1 @@ - -# WinCCWrapper Overview {#winccwrapper_overview} - -## General - -### Description/Summary - -The WinCCWrapper library is a simple C++ wrapper around the difficult to use WinCC_OA API. Of course one could always still choose use the WinCC_OA API which provides more features than this simple wrapper. This WinCCWrapper is aimed at providing a simple API to set and get datapoints into a wincc database. All calls are blocking/synchronous (where the underlying WinCC_OA API is asynchronous). - -This WinCCWrapper library has the following features: -- set/get datapoints for the most common datatypes (int, long, float, bool, string, time_t) -- mark datapoints as valid/invalid. -- "connect" to changes in datapoints: whenever a 'connected' datapoint is changed (by whoever from whereever) then a supplied callback function is called. - -Boost-python bindings are provided as well, exposing the same API in python. - - -### Authors/Owners - -- Auke Klazema <mailto:klazema@astron.nl> -- Jorrit Schaap <mailto:schaap@astron.nl> - -### Overview - -This package builds a c++ library, and python bindings. For further details, see Description above. - -- - - - -## DEVELOPMENT - -### Analyses -This library originated from the Responsive Telescope project which needed a means to use the station monitoring information available in the wincc database. It was later extended in the APERTIF project to provide a means to set/get the validness of datapoints. - -The folling feaures were required, and implemented: -- set/get datapoints for the most common datatypes (int, long, float, bool, string, time_t) -- mark datapoints as valid/invalid. -- "connect" to changes in datapoints: whenever a 'connected' datapoint is changed (by whoever from whereever) then a supplied callback function is called. - -Because the WinCC_OA API is hard to use, we decided to implement this simple wrapper. -Because the WinCC_OA API is in C++, this wrapper needed to be written in C++ as well. -Because we needed to have the same API available in python as well, we decided to create boost-python bindings. - - -### Design -No fancy design needed. This is just a library with a few classes wrapping the complicated WinCC_OA API into a simple API. - -### Source Code -- [WinCCWrapper in SVN](https://svn.astron.nl/LOFAR/branches/SW-26_WinCC/LCS/WinCCWrapper) -- [WinCCWrapper Code Documentation](@ref winccwrapper_overview) - -### Testing - -#### Unit Testing - -We decided not to provide unit tests, because that would require to write a quite large mocked version of the WinCC_OA API, which would be bigger and more complex than the wrapper classes themselves. - -#### Integration Testing - -When BUILD_TESTING is ON, then little test programs are built: WinCCSet and WinCCGet. They can be run from the cmdline (on a host where WinCC is running) and be used to test whether you can successfully set and/or get a datapoint. This is a manual test. - -#### Build & Deploy - -This library needs a c++11 compiler. -Dependencies on other libraries are automatically found by cmake, and otherwise reported which are missing. - -##### Build locally - - svn co https://svn.astron.nl/LOFAR/<some_branch_or_trunk> <my_source_dir> - cd <my_source_dir> - mkdir -p build/gnu_cxx11debug - cd build/gnu_cxx11debug - cmake -DBUILD_PACKAGES=WinCCWrapper -DUSE_LOG4CPLUS=OFF -DCMAKE_INSTALL_PREFIX=/opt/lofar/ ../.. - cd ../.. - make - make install - -##### Build using Jenkins - -There are no special Jenkins jobs for this package specifically. Such a job is also not needed. CMake will automatically take care of building this package whenever a package which is build by Jenkins is dependent on WinCCWrapper. - -##### Deploy - -There is no special Jenkins job to deploy this package specifically. Such a job is also not needed. The library from this package is deployed automatically thanks to cmake/jenkins whenever another package is deployed which depends on this package. - -- - - - -## OPERATIONS - -### Configuration -- There are no configuration files. - -### Log Files -- This library does not produce log files. A program using this library could produce logfiles, and these log files will contain the log lines issued by this library. - -### Runtime -- This library just loads whenever a using program is started. - -### Interfaces (API) -- It's a library. See the source code documentation for the api. - -### Files/Databases -- It depends on a running WINCC_OA instance (which run on the mcu's) -- No other files and/or databases are needed. - -### Dependencies -- WINCC_OA 3.15 (API, and runtime, which are installed on mcu's and the buildhostcentos7) - -### Security -- No login credentials are needed. - -- - - - -## ADDITIONAL INFORMATION - -### User Documentation - -N.A. - -### Operations Documentation - -N.A. - - - +# See lofar/trunk/sw_documentation_template.md for example \ No newline at end of file diff --git a/LCS/WinCCWrapper/include/WinCCManager.h b/LCS/WinCCWrapper/include/WinCCManager.h index d141e328f9e0b3547f181e007cd7e93dd9349a62..e20173301ce710a339820b9be779fad17ede6c8b 100644 --- a/LCS/WinCCWrapper/include/WinCCManager.h +++ b/LCS/WinCCWrapper/include/WinCCManager.h @@ -69,6 +69,8 @@ public: 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. 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. + bool get_datapoint(const std::string &name, DynVar &value); //! 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); } diff --git a/LCS/WinCCWrapper/include/WinCCWrapper.h b/LCS/WinCCWrapper/include/WinCCWrapper.h index f0ff473175fada29a82e78ed95fda695bb91c093..f81fa55ea6c834e6c668863a3257bf895584239f 100644 --- a/LCS/WinCCWrapper/include/WinCCWrapper.h +++ b/LCS/WinCCWrapper/include/WinCCWrapper.h @@ -60,6 +60,8 @@ public: bool set_datapoint(const std::string &name, std::string value, bool valid=true); //! set the datapoint with given name to the given time_t value, mark it valid/invalid, returns true upon success. bool set_datapoint_time(const std::string &name, time_t value, bool valid=true); + //! set the datapoint with given name to the given DynVar value, mark it valid/invalid, returns true upon success. + bool set_datapoint(const std::string &name, DynVar value, bool valid=true); //! mark the datapoint with given name valid. bool set_datapoint_valid(const std::string &name); @@ -78,6 +80,8 @@ public: 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. time_t get_datapoint_time(const std::string &name); + //! get the datapoint with the given name and return it as a DynVar value if possible, otherwise an exception is raised. + DynVar get_datapoint_DynVar(const std::string &name); private: // get_datapoint diff --git a/LCS/WinCCWrapper/src/WinCCManager.cc b/LCS/WinCCWrapper/src/WinCCManager.cc index 217023ca010283a83cc3c5208ed036722857efbe..6b311931ec905e2820eac1f101ac223a9c89b76f 100644 --- a/LCS/WinCCWrapper/src/WinCCManager.cc +++ b/LCS/WinCCWrapper/src/WinCCManager.cc @@ -33,6 +33,7 @@ #include <LongVar.hxx> #include <TextVar.hxx> #include <cassert> +#include <DynVar.hxx> namespace LOFAR { namespace WINCCWRAPPER { @@ -285,6 +286,19 @@ Variable::ConvertResult convert(Variable *var, struct tm &value, Variable *&conv return cr; } +template <> +Variable::ConvertResult convert(Variable *var, int[] &value, Variable *&converted_var) +{ + Variable::ConvertResult cr = var->convert(VariableType::DYN_VAR, converted_var); + if(Variable::ConvertResult::OK == cr) { + for (int i = 0; i < value.getNumberOfItems(); i++) { + value[i] = ((DynVar*)converted_var)->getNext(); + } + } + + return cr; +} + //internal generic method to get the typed (Tval) value of a datapoint //used by the public strictly typed methods template <typename Tval> @@ -342,6 +356,11 @@ bool WinCCManager::get_datapoint(const std::string &name, struct tm &value) return _get_datapoint(name, value); } +bool WinCCManager::get_datapoint(const std::string &name, DynVar &value) +{ + return _get_datapoint(name, value); +} + bool WinCCManager::set_datapoint_validity(const std::string &name, bool validity, const Variable *value) { DpIdentifier dpId; @@ -387,7 +406,7 @@ bool WinCCManager::set_datapoint_validity(const std::string &name, bool validity //delete it, since it was a cloned variable created in get_datapoint_variable delete last_known_value; } - + return true; } @@ -425,7 +444,7 @@ void WinCCManager::handle_hotlink(const std::string &name, const std::string &va if(callback) { callback(name, value); - } + } } void WinCCManager::signalHandler(int sig) diff --git a/LCS/WinCCWrapper/src/WinCCWrapper.cc b/LCS/WinCCWrapper/src/WinCCWrapper.cc index 19883c0a99a3d44c0a95091f67c1f4ff34ece726..239e30f6b1faf193cc15bbf5009aac6985353de4 100644 --- a/LCS/WinCCWrapper/src/WinCCWrapper.cc +++ b/LCS/WinCCWrapper/src/WinCCWrapper.cc @@ -22,6 +22,7 @@ #include <FloatVar.hxx> #include <LongVar.hxx> #include <TimeVar.hxx> +#include <DynVar.hxx> #include <condition_variable> #include <mutex> @@ -68,7 +69,7 @@ void WinCCWrapper::set_connect_datapoints_callback(std::function<void(std::strin // set_datapoint bool WinCCWrapper::set_datapoint(const std::string &name, int value, bool valid) { - IntegerVar variable{value}; + IntegerVar variable{value}; return manager->set_datapoint(name + DP_SUFFIX, variable, valid); } @@ -109,6 +110,13 @@ bool WinCCWrapper::set_datapoint_time(const std::string &name, time_t value, boo return manager->set_datapoint(name + DP_SUFFIX, variable, valid); } +bool WinCCWrapper::set_datapoint(const std::string &name, DynVar value, bool valid) +{ + DynVar variable{value}; + + return manager->set_datapoint(name + DP_SUFFIX, variable, valid); +} + // get_datapoint template <typename T> bool WinCCWrapper::get_datapoint(const std::string &name, T &value) @@ -164,6 +172,14 @@ time_t WinCCWrapper::get_datapoint_time(const std::string &name) throw std::runtime_error("Could not get datapoint"); } +DynVar WinCCWrapper::get_datapoint_DynVar(const std::string &name) +{ + DynVar value; + if(get_datapoint(name, value)) + return value; + throw std::runtime_error("Could not get datapoint"); +} + bool WinCCWrapper::set_datapoint_valid(const std::string &name) { return manager->set_datapoint_valid(name + DP_SUFFIX); diff --git a/LCS/WinCCWrapper/src/WinCCWrapper_boost_python.cc b/LCS/WinCCWrapper/src/WinCCWrapper_boost_python.cc index 50f32eb0f950ebdfb7890b1d3964b39ce05caaa1..f635cbc1f704786ca825afad5d644bbd5ad12e70 100644 --- a/LCS/WinCCWrapper/src/WinCCWrapper_boost_python.cc +++ b/LCS/WinCCWrapper/src/WinCCWrapper_boost_python.cc @@ -33,6 +33,7 @@ BOOST_PYTHON_MODULE(pywincc) bool (WinCCWrapper::*set_datapoint_time)(const std::string&, time_t, bool) = &WinCCWrapper::set_datapoint_time; 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_DynVar)(const std::string&, DynVar, bool) = &WinCCWrapper::set_datapoint; class_<WinCCWrapper>("WinCCWrapper", init<const std::string&>()) .def("set_datapoint_int", set_datapoint_int) @@ -44,6 +45,7 @@ BOOST_PYTHON_MODULE(pywincc) .def("set_datapoint", set_datapoint_float) // 'common'/'generic' set_datapoint python method just calls set_datapoint_float .def("set_datapoint_valid", set_datapoint_valid) .def("set_datapoint_invalid", set_datapoint_invalid) + .def("set_datapoint_DynVar", set_datapoint_DynVar) .def("get_datapoint_int", &WinCCWrapper::get_datapoint_int) .def("get_datapoint_long", &WinCCWrapper::get_datapoint_long) .def("get_datapoint_float", &WinCCWrapper::get_datapoint_float) @@ -51,6 +53,7 @@ BOOST_PYTHON_MODULE(pywincc) .def("get_datapoint_string", &WinCCWrapper::get_datapoint_string) .def("get_datapoint_time", &WinCCWrapper::get_datapoint_time) .def("get_datapoint", &WinCCWrapper::get_datapoint_float) // 'common'/'generic' get_datapoint python method just calls get_datapoint_float + .def("get_datapoint_DynVar", &WinCCWrapper:get_datapoint_DynVar) ; } diff --git a/LCS/WinCCWrapper/test/WinCCGet.cc b/LCS/WinCCWrapper/test/WinCCGet.cc index c050990c75186f4a1d938cb59b63d72945383641..0293c530d7da1ba9728308a0ff9ab3f7d6d815ed 100644 --- a/LCS/WinCCWrapper/test/WinCCGet.cc +++ b/LCS/WinCCWrapper/test/WinCCGet.cc @@ -13,6 +13,6 @@ int main(int, char * argv[]) value = wrapper.get_datapoint_int(dpname); std::cout << dpname << ": " << value << std::endl; - + return 0; }