From dd09ef226c8ea913f68d3011debbfbd1b80461c0 Mon Sep 17 00:00:00 2001 From: gscalamera <graziano.scalamera@elettra.eu> Date: Fri, 6 Dec 2024 09:37:40 +0100 Subject: [PATCH] First import --- .gitignore | 8 + .gitmodules | 6 + Makefile | 8 + deps/socket2 | 1 + deps/socket2client | 1 + docs/Blocco_dati_SCAMBIO.pdf | Bin 0 -> 53810 bytes src/ClassFactory.cpp | 52 +++ src/PLCRack3.cpp | 742 +++++++++++++++++++++++++++++++ src/PLCRack3.h | 441 +++++++++++++++++++ src/PLCRack3.xmi | 153 +++++++ src/PLCRack3Class.cpp | 826 +++++++++++++++++++++++++++++++++++ src/PLCRack3Class.h | 313 +++++++++++++ src/PLCRack3StateMachine.cpp | 331 ++++++++++++++ src/main.cpp | 88 ++++ src/plcsrvthread.cpp | 406 +++++++++++++++++ src/plcsrvthread.h | 92 ++++ 16 files changed, 3468 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 160000 deps/socket2 create mode 160000 deps/socket2client create mode 100644 docs/Blocco_dati_SCAMBIO.pdf create mode 100644 src/ClassFactory.cpp create mode 100644 src/PLCRack3.cpp create mode 100644 src/PLCRack3.h create mode 100644 src/PLCRack3.xmi create mode 100644 src/PLCRack3Class.cpp create mode 100644 src/PLCRack3Class.h create mode 100644 src/PLCRack3StateMachine.cpp create mode 100644 src/main.cpp create mode 100644 src/plcsrvthread.cpp create mode 100644 src/plcsrvthread.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d4c718 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.nse_depinfo +bin +obj + +# Eclipse +.cproject +.project +.settings diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..135ddcf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "deps/socket2"] + path = deps/socket2 + url = git@gitlab.elettra.eu:cs/ds/socket2.git +[submodule "deps/socket2client"] + path = deps/socket2client + url = git@gitlab.elettra.eu:cs/cls/socket2client.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5b384bc --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +NAME_SRV = plcrack3-srv + +CXXFLAGS = -I ../socket2/src +SRC_FILES = $(wildcard deps/socket2*/src/Socket2*.cpp) +CXXFLAGS = -Ideps/socket2client/src -Ideps/socket2/src + + +include ../makefiles/Make-9.3.6.in diff --git a/deps/socket2 b/deps/socket2 new file mode 160000 index 0000000..36fd91b --- /dev/null +++ b/deps/socket2 @@ -0,0 +1 @@ +Subproject commit 36fd91bbeb50e33556cd5dfd73888552dd0a69d6 diff --git a/deps/socket2client b/deps/socket2client new file mode 160000 index 0000000..0f51d74 --- /dev/null +++ b/deps/socket2client @@ -0,0 +1 @@ +Subproject commit 0f51d74c0c1f1e3aae5bf5a3ce4e9cbbea80face diff --git a/docs/Blocco_dati_SCAMBIO.pdf b/docs/Blocco_dati_SCAMBIO.pdf new file mode 100644 index 0000000000000000000000000000000000000000..574dc6e7bd1b3842ea2a9f908dae8ceaebc5fa24 GIT binary patch literal 53810 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 literal 0 HcmV?d00001 diff --git a/src/ClassFactory.cpp b/src/ClassFactory.cpp new file mode 100644 index 0000000..18658ec --- /dev/null +++ b/src/ClassFactory.cpp @@ -0,0 +1,52 @@ +/*----- PROTECTED REGION ID(PLCRack3::ClassFactory.cpp) ENABLED START -----*/ +/* clang-format on */ +//============================================================================= +// +// file : ClassFactory.cpp +// +// description : C++ source for the class_factory method of the DServer +// device class. This method is responsible for the creation of +// all class singleton for a device server. It is called +// at device server startup. +// +// project : PLCRack3 +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or 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 option) any later version. +// +// Tango 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= + +#include <tango.h> +#include "PLCRack3Class.h" + +// Add class header files if needed + + +/** + * Create PLCRack3 Class singleton and store it in DServer object. + */ + +void Tango::DServer::class_factory() +{ + // Add method class init if needed + add_class(PLCRack3_ns::PLCRack3Class::init("PLCRack3")); +} +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::ClassFactory.cpp diff --git a/src/PLCRack3.cpp b/src/PLCRack3.cpp new file mode 100644 index 0000000..eaa572d --- /dev/null +++ b/src/PLCRack3.cpp @@ -0,0 +1,742 @@ +/*----- PROTECTED REGION ID(PLCRack3.cpp) ENABLED START -----*/ +/* clang-format on */ +//============================================================================= +// +// file : PLCRack3.cpp +// +// description : C++ source for the PLCRack3 class and its commands. +// The class is derived from Device. It represents the +// CORBA servant object which will be accessed from the +// network. All commands which can be executed on the +// PLCRack3 are implemented in this file. +// +// project : PLCRack3 +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or 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 option) any later version. +// +// Tango 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= + + +#include "PLCRack3.h" +#include "PLCRack3Class.h" +#include "plcsrvthread.h" +#include <iomanip> //used for debug dump of db +#include <netdb.h> +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3.cpp + +/** + * PLCRack3 class description: + * PLC Rack Triplo + */ + +//================================================================ +// The following table gives the correspondence +// between command and method names. +// +// Command name | Method name +//================================================================ +// State | Inherited (no method) +// Status | Inherited (no method) +//================================================================ + +//================================================================ +// Attributes managed are: +//================================================================ +// sezione2Temp | Tango::DevDouble Scalar +// sezione1Temp | Tango::DevDouble Scalar +// buncherTemp | Tango::DevDouble Scalar +// sezione2State | Tango::DevBoolean Scalar +// sezione1State | Tango::DevBoolean Scalar +// buncherState | Tango::DevBoolean Scalar +// sezione2FSHighState | Tango::DevBoolean Scalar +// sezione2TSState | Tango::DevBoolean Scalar +// sezione1FSHighState | Tango::DevBoolean Scalar +// sezione1TSState | Tango::DevBoolean Scalar +// buncherFSHighState | Tango::DevBoolean Scalar +// buncherTSState | Tango::DevBoolean Scalar +// sezione2FSLowState | Tango::DevBoolean Scalar +// sezione1FSLowState | Tango::DevBoolean Scalar +// buncherFSLowState | Tango::DevBoolean Scalar +//================================================================ + +namespace PLCRack3_ns +{ +/*----- PROTECTED REGION ID(PLCRack3::namespace_starting) ENABLED START -----*/ +/* clang-format on */ +// static initializations +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::namespace_starting + +//-------------------------------------------------------- +/** + * Method : PLCRack3::PLCRack3() + * Description: Constructors for a Tango device + * implementing the classPLCRack3 + */ +//-------------------------------------------------------- +PLCRack3::PLCRack3(Tango::DeviceClass *cl, std::string &s) + : Socket2Client(cl, s.c_str()) +{ + /*----- PROTECTED REGION ID(PLCRack3::constructor_1) ENABLED START -----*/ + /* clang-format on */ + init_device(); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::constructor_1 +} +//-------------------------------------------------------- +PLCRack3::PLCRack3(Tango::DeviceClass *cl, const char *s) + : Socket2Client(cl, s) +{ + /*----- PROTECTED REGION ID(PLCRack3::constructor_2) ENABLED START -----*/ + /* clang-format on */ + init_device(); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::constructor_2 +} +//-------------------------------------------------------- +PLCRack3::PLCRack3(Tango::DeviceClass *cl, const char *s, const char *d) + : Socket2Client(cl, s, d) +{ + /*----- PROTECTED REGION ID(PLCRack3::constructor_3) ENABLED START -----*/ + /* clang-format on */ + init_device(); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::constructor_3 +} +//-------------------------------------------------------- +PLCRack3::~PLCRack3() +{ + delete_device(); +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::delete_device() + * Description: will be called at device destruction or at init command + */ +//-------------------------------------------------------- +void PLCRack3::delete_device() +{ + DEBUG_STREAM << "PLCRack3::delete_device() " << device_name << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::delete_device) ENABLED START -----*/ + /* clang-format on */ + // Delete device allocated objects + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::delete_device + delete[] attr_sezione2Temp_read; + delete[] attr_sezione1Temp_read; + delete[] attr_buncherTemp_read; + delete[] attr_sezione2State_read; + delete[] attr_sezione1State_read; + delete[] attr_buncherState_read; + delete[] attr_sezione2FSHighState_read; + delete[] attr_sezione2TSState_read; + delete[] attr_sezione1FSHighState_read; + delete[] attr_sezione1TSState_read; + delete[] attr_buncherFSHighState_read; + delete[] attr_buncherTSState_read; + delete[] attr_sezione2FSLowState_read; + delete[] attr_sezione1FSLowState_read; + delete[] attr_buncherFSLowState_read; + + if (Tango::Util::instance()->is_svr_shutting_down()==false && + Tango::Util::instance()->is_device_restarting(device_name)==false && + Tango::Util::instance()->is_svr_starting()==false) + { + // If not shutting down call delete device for inherited object + Socket2Client_ns::Socket2Client::delete_device(); + } +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::init_device() + * Description: will be called at device initialization. + */ +//-------------------------------------------------------- +void PLCRack3::init_device() +{ + DEBUG_STREAM << "PLCRack3::init_device() create device " << device_name << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::init_device_before) ENABLED START -----*/ + /* clang-format on */ + // Initialization before get_device_property() call + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::init_device_before + + if (Tango::Util::instance()->is_svr_starting() == false && + Tango::Util::instance()->is_device_restarting(device_name)==false) + { + // If not starting up call init device for inherited object + Socket2Client_ns::Socket2Client::init_device(); + } + // No device property to be read from database + + attr_sezione2Temp_read = new Tango::DevDouble[1]; + attr_sezione1Temp_read = new Tango::DevDouble[1]; + attr_buncherTemp_read = new Tango::DevDouble[1]; + attr_sezione2State_read = new Tango::DevBoolean[1]; + attr_sezione1State_read = new Tango::DevBoolean[1]; + attr_buncherState_read = new Tango::DevBoolean[1]; + attr_sezione2FSHighState_read = new Tango::DevBoolean[1]; + attr_sezione2TSState_read = new Tango::DevBoolean[1]; + attr_sezione1FSHighState_read = new Tango::DevBoolean[1]; + attr_sezione1TSState_read = new Tango::DevBoolean[1]; + attr_buncherFSHighState_read = new Tango::DevBoolean[1]; + attr_buncherTSState_read = new Tango::DevBoolean[1]; + attr_sezione2FSLowState_read = new Tango::DevBoolean[1]; + attr_sezione1FSLowState_read = new Tango::DevBoolean[1]; + attr_buncherFSLowState_read = new Tango::DevBoolean[1]; + // No longer if mandatory property not set. + if (mandatoryNotDefined) + return; + + /*----- PROTECTED REGION ID(PLCRack3::init_device) ENABLED START -----*/ + /* clang-format on */ + // Initialize device + loop = new plcsrvthread(this); + loop->start(); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::init_device +} + + +//-------------------------------------------------------- +/** + * Method : PLCRack3::always_executed_hook() + * Description: method always executed before any command is executed + */ +//-------------------------------------------------------- +void PLCRack3::always_executed_hook() +{ + DEBUG_STREAM << "PLCRack3::always_executed_hook() " << device_name << std::endl; + if (mandatoryNotDefined) + { + Tango::Except::throw_exception( + (const char *)"PROPERTY_NOT_SET", + get_status().c_str(), + (const char *)"PLCRack3::always_executed_hook()"); + } + /*----- PROTECTED REGION ID(PLCRack3::always_executed_hook) ENABLED START -----*/ + /* clang-format on */ + // code always executed before all requests + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::always_executed_hook +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::read_attr_hardware() + * Description: Hardware acquisition for attributes + */ +//-------------------------------------------------------- +void PLCRack3::read_attr_hardware(TANGO_UNUSED(std::vector<long> &attr_list)) +{ + DEBUG_STREAM << "PLCRack3::read_attr_hardware(std::vector<long> &attr_list) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_attr_hardware) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_attr_hardware +} +//-------------------------------------------------------- +/** + * Method : PLCRack3::write_attr_hardware() + * Description: Hardware writing for attributes + */ +//-------------------------------------------------------- +void PLCRack3::write_attr_hardware(TANGO_UNUSED(std::vector<long> &attr_list)) +{ + DEBUG_STREAM << "PLCRack3::write_attr_hardware(std::vector<long> &attr_list) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::write_attr_hardware) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::write_attr_hardware +} + +//-------------------------------------------------------- +/** + * Read attribute sezione2Temp related method + * + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione2Temp(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione2Temp(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione2Temp) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione2Temp_read = (double)(ntohs(db500.temp_sez2))/100.0; + attr.set_value(attr_sezione2Temp_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione2Temp +} +//-------------------------------------------------------- +/** + * Read attribute sezione1Temp related method + * + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione1Temp(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione1Temp(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione1Temp) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione1Temp_read = (double)(ntohs(db500.temp_sez1))/100.0; + attr.set_value(attr_sezione1Temp_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione1Temp +} +//-------------------------------------------------------- +/** + * Read attribute buncherTemp related method + * + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_buncherTemp(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_buncherTemp(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_buncherTemp) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_buncherTemp_read = (double)(ntohs(db500.temp_buncher))/100.0; + attr.set_value(attr_buncherTemp_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_buncherTemp +} +//-------------------------------------------------------- +/** + * Read attribute sezione2State related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione2State(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione2State(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione2State) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione2State_read = (Tango::DevBoolean)(db500.stato_sez2 != 0); + attr.set_value(attr_sezione2State_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione2State +} +//-------------------------------------------------------- +/** + * Write attribute sezione2State related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::write_sezione2State(Tango::WAttribute &attr) +{ + DEBUG_STREAM << "PLCRack3::write_sezione2State(Tango::WAttribute &attr) entering... " << std::endl; + // Retrieve write value + Tango::DevBoolean w_val; + attr.get_write_value(w_val); + /*----- PROTECTED REGION ID(PLCRack3::write_sezione2State) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + if(w_val) + send_cmd(StartSez2Cmd); + else + send_cmd(StopSez2Cmd); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::write_sezione2State +} +//-------------------------------------------------------- +/** + * Read attribute sezione1State related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione1State(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione1State(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione1State) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione1State_read = (Tango::DevBoolean)(db500.stato_sez1 != 0); + attr.set_value(attr_sezione1State_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione1State +} +//-------------------------------------------------------- +/** + * Write attribute sezione1State related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::write_sezione1State(Tango::WAttribute &attr) +{ + DEBUG_STREAM << "PLCRack3::write_sezione1State(Tango::WAttribute &attr) entering... " << std::endl; + // Retrieve write value + Tango::DevBoolean w_val; + attr.get_write_value(w_val); + /*----- PROTECTED REGION ID(PLCRack3::write_sezione1State) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + if(w_val) + send_cmd(StartSez1Cmd); + else + send_cmd(StopSez1Cmd); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::write_sezione1State +} +//-------------------------------------------------------- +/** + * Read attribute buncherState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_buncherState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_buncherState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_buncherState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_buncherState_read = (Tango::DevBoolean)(db500.stato_buncher != 0); + attr.set_value(attr_buncherState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_buncherState +} +//-------------------------------------------------------- +/** + * Write attribute buncherState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::write_buncherState(Tango::WAttribute &attr) +{ + DEBUG_STREAM << "PLCRack3::write_buncherState(Tango::WAttribute &attr) entering... " << std::endl; + // Retrieve write value + Tango::DevBoolean w_val; + attr.get_write_value(w_val); + /*----- PROTECTED REGION ID(PLCRack3::write_buncherState) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + if(w_val) + send_cmd(StartBuncherCmd); + else + send_cmd(StopBuncherCmd); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::write_buncherState +} +//-------------------------------------------------------- +/** + * Read attribute sezione2FSHighState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione2FSHighState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione2FSHighState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione2FSHighState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione2FSHighState_read = (Tango::DevBoolean)(db500.limite_superiore_portata2 != 0); + attr.set_value(attr_sezione2FSHighState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione2FSHighState +} +//-------------------------------------------------------- +/** + * Read attribute sezione2TSState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione2TSState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione2TSState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione2TSState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione2TSState_read = (Tango::DevBoolean)(db500.termostato_resistenza2 != 0); + attr.set_value(attr_sezione2TSState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione2TSState +} +//-------------------------------------------------------- +/** + * Read attribute sezione1FSHighState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione1FSHighState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione1FSHighState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione1FSHighState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione1FSHighState_read = (Tango::DevBoolean)(db500.limite_superiore_portata1 != 0); + attr.set_value(attr_sezione1FSHighState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione1FSHighState +} +//-------------------------------------------------------- +/** + * Read attribute sezione1TSState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione1TSState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione1TSState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione1TSState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione1TSState_read = (Tango::DevBoolean)(db500.termostato_resistenza1 != 0); + attr.set_value(attr_sezione1TSState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione1TSState +} +//-------------------------------------------------------- +/** + * Read attribute buncherFSHighState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_buncherFSHighState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_buncherFSHighState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_buncherFSHighState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_buncherFSHighState_read = (Tango::DevBoolean)(db500.limite_superiore_portata3 != 0); + attr.set_value(attr_buncherFSHighState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_buncherFSHighState +} +//-------------------------------------------------------- +/** + * Read attribute buncherTSState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_buncherTSState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_buncherTSState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_buncherTSState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_buncherTSState_read = (Tango::DevBoolean)(db500.termostato_resistenza3 != 0); + attr.set_value(attr_buncherTSState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_buncherTSState +} +//-------------------------------------------------------- +/** + * Read attribute sezione2FSLowState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione2FSLowState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione2FSLowState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione2FSLowState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione2FSLowState_read = (Tango::DevBoolean)(db500.limite_inferiore_portata2 != 0); + attr.set_value(attr_sezione2FSLowState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione2FSLowState +} +//-------------------------------------------------------- +/** + * Read attribute sezione1FSLowState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_sezione1FSLowState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_sezione1FSLowState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_sezione1FSLowState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_sezione1FSLowState_read = (Tango::DevBoolean)(db500.limite_inferiore_portata1 != 0); + attr.set_value(attr_sezione1FSLowState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_sezione1FSLowState +} +//-------------------------------------------------------- +/** + * Read attribute buncherFSLowState related method + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void PLCRack3::read_buncherFSLowState(Tango::Attribute &attr) +{ + DEBUG_STREAM << "PLCRack3::read_buncherFSLowState(Tango::Attribute &attr) entering... " << std::endl; + /*----- PROTECTED REGION ID(PLCRack3::read_buncherFSLowState) ENABLED START -----*/ + /* clang-format on */ + // Set the attribute value + *attr_buncherFSLowState_read = (Tango::DevBoolean)(db500.limite_inferiore_buncher != 0); + attr.set_value(attr_buncherFSLowState_read); + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::read_buncherFSLowState +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::add_dynamic_attributes() + * Description: Create the dynamic attributes if any + * for specified device. + */ +//-------------------------------------------------------- +void PLCRack3::add_dynamic_attributes() +{ + /*----- PROTECTED REGION ID(PLCRack3::add_dynamic_attributes) ENABLED START -----*/ + /* clang-format on */ + // Add your own code to create and add dynamic attributes if any + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::add_dynamic_attributes +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::add_dynamic_commands() + * Description: Create the dynamic commands if any + * for specified device. + */ +//-------------------------------------------------------- +void PLCRack3::add_dynamic_commands() +{ + /*----- PROTECTED REGION ID(PLCRack3::add_dynamic_commands) ENABLED START -----*/ + /* clang-format on */ + // Add your own code to create and add dynamic commands if any + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::add_dynamic_commands +} + +/*----- PROTECTED REGION ID(PLCRack3::namespace_ending) ENABLED START -----*/ +/* clang-format on */ +// Additional Methods +void PLCRack3::send_cmd (uint16_t cmd) +{ + cmd_t prepared_cmd; + memset(&prepared_cmd, 0, sizeof(cmd_t)); + prepared_cmd.db_number=htons(cmd); + try { + send_frame((unsigned char *)&prepared_cmd, sizeof(cmd_t)); + } + catch(Tango::DevFailed e) { + set_state(Tango::FAULT); + set_status("Write command failed"); + Tango::Except::re_throw_exception(e, + (const char *) "write error", + (const char *) "write cmd error", + (const char *) "PLCRack3::send_cmd", Tango::ERR); + } +} +void PLCRack3::send_frame (unsigned char *query, size_t query_length) +{ + + for(size_t k=0;k<query_length;) + { + stringstream tmp; + size_t g; + tmp << "dbTX: "<<setw(3)<<setfill(' ')<<k<<" -> "; + for(g=0; g<10; g++) + { + if(k+g>=query_length) + break; + tmp << " " <<hex<<setw(2)<<setfill(' ')<< (int)(unsigned char)query[k+g]; + } + k+=g; + if(k<query_length) + { + tmp << " | "<<dec<<setw(3)<<setfill(' ')<<k<<hex<<" -> "; + for(g=0; g<10; g++) + { + if(k+g>=query_length) + break; + tmp << " " <<hex<<setw(2)<<setfill(' ')<< (int)(unsigned char)query[k+g]; + } + k+=g; + } + DEBUG_STREAM<<tmp.str()<<dec<<endl; + } + + vector<unsigned char> dtw; + dtw.reserve(query_length); + for (unsigned int i=0; i<query_length; ++i) + dtw.push_back(query[i]); + + write(dtw); +} +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::namespace_ending +} // namespace diff --git a/src/PLCRack3.h b/src/PLCRack3.h new file mode 100644 index 0000000..1bfaa2c --- /dev/null +++ b/src/PLCRack3.h @@ -0,0 +1,441 @@ +/*----- PROTECTED REGION ID(PLCRack3.h) ENABLED START -----*/ +/* clang-format on */ +//============================================================================= +// +// file : PLCRack3.h +// +// description : Include file for the PLCRack3 class +// +// project : PLCRack3 +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or 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 option) any later version. +// +// Tango 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= + + +#ifndef PLCRack3_H +#define PLCRack3_H + +#include <tango.h> +#include <Socket2Client.h> + +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3.h + +#ifdef TANGO_LOG + // cppTango after c934adea (Merge branch 'remove-cout-definition' into 'main', 2022-05-23) + // nothing to do +#else + // cppTango 9.3-backports and older + #define TANGO_LOG cout + #define TANGO_LOG_INFO cout2 + #define TANGO_LOG_DEBUG cout3 +#endif // TANGO_LOG + +constexpr uint16_t StartSez1Cmd=200; +constexpr uint16_t StartSez2Cmd=201; +constexpr uint16_t StartBuncherCmd=202; +constexpr uint16_t StopSez1Cmd=210; +constexpr uint16_t StopSez2Cmd=211; +constexpr uint16_t StopBuncherCmd=212; + +/** + * PLCRack3 class description: + * PLC Rack Triplo + */ + + +namespace PLCRack3_ns +{ +/*----- PROTECTED REGION ID(PLCRack3::Additional Class Declarations) ENABLED START -----*/ +/* clang-format on */ +class plcsrvthread; +// Additional Class Declarations +#pragma pack(push,1) // exact fit - no padding + +typedef struct +{ + uint8_t timestamp[8]; +} date_and_time_t; + +typedef struct +{ + int16_t db_number; + date_and_time_t db_time; +} header_t; + +//DB XX +//typedef struct +//{ +// int16_t db_number; +// date_and_time_t db_time; +// uint16_t code; +//} cmd_t; + +//DB XX +typedef struct +{ + int16_t db_number; + date_and_time_t db_time; + uint16_t temp_sez1; + uint16_t temp_sez2; + uint16_t temp_buncher; +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t stato_sez2:1, //8.7 + stato_sez1:1, + stop_buncher:1, + stop_sez2:1, + stop_sez1:1, + start_buncher:1, + start_sez2:1, + start_sez1:1; //8.0 +#else + uint8_t start_sez1:1, //8.0 + start_sez2:1, + start_buncher:1, + stop_sez1:1, + stop_sez2:1, + stop_buncher:1, + stato_sez1:1, + stato_sez2:1; //8.7 +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t termostato_resistenza1:1, //9.7 + limite_superiore_portata3:1, + limite_superiore_portata2:1, + limite_superiore_portata1:1, + limite_inferiore_buncher:1, + limite_inferiore_portata2:1, + limite_inferiore_portata1:1, + stato_buncher:1; //9.0 +#else + uint8_t stato_buncher:1, //9.0 + limite_inferiore_portata1:1, + limite_inferiore_portata2:1, + limite_inferiore_buncher:1, + limite_superiore_portata1:1, + limite_superiore_portata2:1, + limite_superiore_portata3:1, + termostato_resistenza1:1; //9.7 +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + uint8_t spare:6, //10.2-10.7 + termostato_resistenza3:1, //10.1 + termostato_resistenza2:1; //10.0 +#else + uint8_t termostato_resistenza2:1, //10.0 + termostato_resistenza3:1, //10.1 + spare:6; //10.2-10.7 +#endif + uint8_t spare_; +} data_t; + +typedef data_t cmd_t; +#pragma pack(pop) //back to whatever the previous packing mode was +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::Additional Class Declarations + +class PLCRack3 : public Socket2Client_ns::Socket2Client +{ + +/*----- PROTECTED REGION ID(PLCRack3::Data Members) ENABLED START -----*/ +/* clang-format on */ +// Add your own data members +public: +bool abortflag; +friend class plcsrvthread; +plcsrvthread *loop; +data_t db500; +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::Data Members + +// Device property data members +public: + + bool mandatoryNotDefined; + +// Attribute data members +public: + Tango::DevDouble *attr_sezione2Temp_read; + Tango::DevDouble *attr_sezione1Temp_read; + Tango::DevDouble *attr_buncherTemp_read; + Tango::DevBoolean *attr_sezione2State_read; + Tango::DevBoolean *attr_sezione1State_read; + Tango::DevBoolean *attr_buncherState_read; + Tango::DevBoolean *attr_sezione2FSHighState_read; + Tango::DevBoolean *attr_sezione2TSState_read; + Tango::DevBoolean *attr_sezione1FSHighState_read; + Tango::DevBoolean *attr_sezione1TSState_read; + Tango::DevBoolean *attr_buncherFSHighState_read; + Tango::DevBoolean *attr_buncherTSState_read; + Tango::DevBoolean *attr_sezione2FSLowState_read; + Tango::DevBoolean *attr_sezione1FSLowState_read; + Tango::DevBoolean *attr_buncherFSLowState_read; + +// Constructors and destructors +public: + /** + * Constructs a newly device object. + * + * @param cl Class. + * @param s Device Name + */ + PLCRack3(Tango::DeviceClass *cl,std::string &s); + /** + * Constructs a newly device object. + * + * @param cl Class. + * @param s Device Name + */ + PLCRack3(Tango::DeviceClass *cl,const char *s); + /** + * Constructs a newly device object. + * + * @param cl Class. + * @param s Device name + * @param d Device description. + */ + PLCRack3(Tango::DeviceClass *cl,const char *s,const char *d); + /** + * The device object destructor. + */ + ~PLCRack3(); + + +// Miscellaneous methods +public: + /* + * will be called at device destruction or at init command. + */ + void delete_device(); + /* + * Initialize the device + */ + virtual void init_device(); + /* + * Always executed method before execution command method. + */ + virtual void always_executed_hook(); + + /* + * Check if mandatory property has been set + */ + void check_mandatory_property(Tango::DbDatum &class_prop, Tango::DbDatum &dev_prop); + +// Attribute methods +public: + //-------------------------------------------------------- + /* + * Method : PLCRack3::read_attr_hardware() + * Description: Hardware acquisition for attributes. + */ + //-------------------------------------------------------- + virtual void read_attr_hardware(std::vector<long> &attr_list); + //-------------------------------------------------------- + /* + * Method : PLCRack3::write_attr_hardware() + * Description: Hardware writing for attributes. + */ + //-------------------------------------------------------- + virtual void write_attr_hardware(std::vector<long> &attr_list); + +/** + * Attribute sezione2Temp related methods + * + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ + virtual void read_sezione2Temp(Tango::Attribute &attr); + virtual bool is_sezione2Temp_allowed(Tango::AttReqType type); +/** + * Attribute sezione1Temp related methods + * + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ + virtual void read_sezione1Temp(Tango::Attribute &attr); + virtual bool is_sezione1Temp_allowed(Tango::AttReqType type); +/** + * Attribute buncherTemp related methods + * + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ + virtual void read_buncherTemp(Tango::Attribute &attr); + virtual bool is_buncherTemp_allowed(Tango::AttReqType type); +/** + * Attribute sezione2State related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione2State(Tango::Attribute &attr); + virtual void write_sezione2State(Tango::WAttribute &attr); + virtual bool is_sezione2State_allowed(Tango::AttReqType type); +/** + * Attribute sezione1State related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione1State(Tango::Attribute &attr); + virtual void write_sezione1State(Tango::WAttribute &attr); + virtual bool is_sezione1State_allowed(Tango::AttReqType type); +/** + * Attribute buncherState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_buncherState(Tango::Attribute &attr); + virtual void write_buncherState(Tango::WAttribute &attr); + virtual bool is_buncherState_allowed(Tango::AttReqType type); +/** + * Attribute sezione2FSHighState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione2FSHighState(Tango::Attribute &attr); + virtual bool is_sezione2FSHighState_allowed(Tango::AttReqType type); +/** + * Attribute sezione2TSState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione2TSState(Tango::Attribute &attr); + virtual bool is_sezione2TSState_allowed(Tango::AttReqType type); +/** + * Attribute sezione1FSHighState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione1FSHighState(Tango::Attribute &attr); + virtual bool is_sezione1FSHighState_allowed(Tango::AttReqType type); +/** + * Attribute sezione1TSState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione1TSState(Tango::Attribute &attr); + virtual bool is_sezione1TSState_allowed(Tango::AttReqType type); +/** + * Attribute buncherFSHighState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_buncherFSHighState(Tango::Attribute &attr); + virtual bool is_buncherFSHighState_allowed(Tango::AttReqType type); +/** + * Attribute buncherTSState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_buncherTSState(Tango::Attribute &attr); + virtual bool is_buncherTSState_allowed(Tango::AttReqType type); +/** + * Attribute sezione2FSLowState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione2FSLowState(Tango::Attribute &attr); + virtual bool is_sezione2FSLowState_allowed(Tango::AttReqType type); +/** + * Attribute sezione1FSLowState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_sezione1FSLowState(Tango::Attribute &attr); + virtual bool is_sezione1FSLowState_allowed(Tango::AttReqType type); +/** + * Attribute buncherFSLowState related methods + * + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void read_buncherFSLowState(Tango::Attribute &attr); + virtual bool is_buncherFSLowState_allowed(Tango::AttReqType type); + + + //-------------------------------------------------------- + /** + * Method : PLCRack3::add_dynamic_attributes() + * Description: Add dynamic attributes if any. + */ + //-------------------------------------------------------- + void add_dynamic_attributes(); + + + + +// Command related methods +public: + + + //-------------------------------------------------------- + /** + * Method : PLCRack3::add_dynamic_commands() + * Description: Add dynamic commands if any. + */ + //-------------------------------------------------------- + void add_dynamic_commands(); + +/*----- PROTECTED REGION ID(PLCRack3::Additional Method prototypes) ENABLED START -----*/ +/* clang-format on */ +// Additional Method prototypes +Tango::DevState socket_get_state(){/*return get_state2();*/return Tango::ON;} +void send_cmd (uint16_t cmd); +void send_frame (unsigned char *query, size_t query_length); +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::Additional Method prototypes +}; + +/*----- PROTECTED REGION ID(PLCRack3::Additional Classes Definitions) ENABLED START -----*/ +/* clang-format on */ +// Additional Classes Definitions +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::Additional Classes Definitions + +} // End of namespace + +#endif // PLCRack3_H diff --git a/src/PLCRack3.xmi b/src/PLCRack3.xmi new file mode 100644 index 0000000..32df4c5 --- /dev/null +++ b/src/PLCRack3.xmi @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="ASCII"?> +<pogoDsl:PogoSystem xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pogoDsl="http://www.esrf.fr/tango/pogo/PogoDsl"> + <classes name="PLCRack3" pogoRevision="9.7"> + <description description="PLC Rack Triplo" title="PLCRack3" sourcePath="/home/graziano/ws/ds/plcrack3/src" language="Cpp" filestogenerate="XMI file,Code files,Protected Regions" license="GPL" copyright="" hasMandatoryProperty="true" hasConcreteProperty="false" hasAbstractCommand="false" hasAbstractAttribute="false"> + <inheritances classname="Device_Impl" sourcePath=""/> + <inheritances classname="Socket2Client" sourcePath="../deps/socket2client/src"/> + <identification contact="at elettra.eu - graziano.scalamera" author="graziano.scalamera" emailDomain="elettra.eu" classFamily="SoftwareSystem" siteSpecific="" platform="Unix Like" bus="Ethernet" manufacturer="none" reference=""/> + </description> + <deviceProperties name="DeviceName" mandatory="true" description=""> + <type xsi:type="pogoDsl:StringType"/> + <status abstract="false" inherited="true" concrete="true"/> + </deviceProperties> + <commands name="State" description="This command gets the device state (stored in its device_state data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0"> + <argin description="none"> + <type xsi:type="pogoDsl:VoidType"/> + </argin> + <argout description="Device state"> + <type xsi:type="pogoDsl:StateType"/> + </argout> + <status abstract="true" inherited="true" concrete="true"/> + </commands> + <commands name="Status" description="This command gets the device status (stored in its device_status data member) and returns it to the caller." execMethod="dev_status" displayLevel="OPERATOR" polledPeriod="0"> + <argin description="none"> + <type xsi:type="pogoDsl:VoidType"/> + </argin> + <argout description="Device status"> + <type xsi:type="pogoDsl:ConstStringType"/> + </argout> + <status abstract="true" inherited="true" concrete="true"/> + </commands> + <attributes name="sezione2Temp" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:DoubleType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione1Temp" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:DoubleType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="buncherTemp" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:DoubleType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione2State" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione1State" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="buncherState" attType="Scalar" rwType="READ_WRITE" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione2FSHighState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione2TSState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione1FSHighState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione1TSState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="buncherFSHighState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="buncherTSState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione2FSLowState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="sezione1FSLowState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <attributes name="buncherFSLowState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false"> + <dataType xsi:type="pogoDsl:BooleanType"/> + <changeEvent fire="false" libCheckCriteria="false"/> + <archiveEvent fire="false" libCheckCriteria="false"/> + <dataReadyEvent fire="false" libCheckCriteria="true"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/> + </attributes> + <preferences docHome="./doc_html" makefileHome="$(TANGO_HOME)"/> + </classes> +</pogoDsl:PogoSystem> diff --git a/src/PLCRack3Class.cpp b/src/PLCRack3Class.cpp new file mode 100644 index 0000000..97561d6 --- /dev/null +++ b/src/PLCRack3Class.cpp @@ -0,0 +1,826 @@ +/*----- PROTECTED REGION ID(PLCRack3Class.cpp) ENABLED START -----*/ +/* clang-format on */ +//============================================================================= +// +// file : PLCRack3Class.cpp +// +// description : C++ source for the PLCRack3Class. +// A singleton class derived from DeviceClass. +// It implements the command and attribute list +// and all properties and methods required +// by the PLCRack3 once per process. +// +// project : PLCRack3 +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or 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 option) any later version. +// +// Tango 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= + + +#include "PLCRack3Class.h" +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3Class.cpp + +//------------------------------------------------------------------- +/** + * Create PLCRack3Class singleton and + * return it in a C function for Python usage + */ +//------------------------------------------------------------------- +extern "C" { +#ifdef _TG_WINDOWS_ + +__declspec(dllexport) + +#endif + + Tango::DeviceClass *_create_PLCRack3_class(const char *name) { + return PLCRack3_ns::PLCRack3Class::init(name); + } +} + +namespace PLCRack3_ns +{ +//=================================================================== +// Initialize pointer for singleton pattern +//=================================================================== +PLCRack3Class *PLCRack3Class::_instance = NULL; + +//=================================================================== +// Class constants +//=================================================================== +//-------------------------------------------------------- +/** + * method : PLCRack3Class::PLCRack3Class(std::string &s) + * description : constructor for the PLCRack3Class + * + * @param s The class name + */ +//-------------------------------------------------------- +PLCRack3Class::PLCRack3Class(std::string &s):Socket2Client_ns::Socket2ClientClass(s) +{ + TANGO_LOG_INFO << "Entering PLCRack3Class constructor" << std::endl; + set_default_property(); + write_class_property(); + + /*----- PROTECTED REGION ID(PLCRack3Class::constructor) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::constructor + + TANGO_LOG_INFO << "Leaving PLCRack3Class constructor" << std::endl; +} + +//-------------------------------------------------------- +/** + * method : PLCRack3Class::~PLCRack3Class() + * description : destructor for the PLCRack3Class + */ +//-------------------------------------------------------- +PLCRack3Class::~PLCRack3Class() +{ + /*----- PROTECTED REGION ID(PLCRack3Class::destructor) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::destructor + + _instance = NULL; +} + + +//-------------------------------------------------------- +/** + * method : PLCRack3Class::init + * description : Create the object if not already done. + * Otherwise, just return a pointer to the object + * + * @param name The class name + */ +//-------------------------------------------------------- +PLCRack3Class *PLCRack3Class::init(const char *name) +{ + if (_instance == NULL) + { + try + { + std::string s(name); + _instance = new PLCRack3Class(s); + } + catch (std::bad_alloc &) + { + throw; + } + } + return _instance; +} + +//-------------------------------------------------------- +/** + * method : PLCRack3Class::instance + * description : Check if object already created, + * and return a pointer to the object + */ +//-------------------------------------------------------- +PLCRack3Class *PLCRack3Class::instance() +{ + if (_instance == NULL) + { + std::cerr << "Class is not initialized !!" << std::endl; + exit(-1); + } + return _instance; +} + + + +//=================================================================== +// Command execution method calls +//=================================================================== + +//=================================================================== +// Properties management +//=================================================================== +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::get_class_property() + * Description: Get the class property for specified name. + */ +//-------------------------------------------------------- +Tango::DbDatum PLCRack3Class::get_class_property(std::string &prop_name) +{ + for (unsigned int i=0 ; i<cl_prop.size() ; i++) + if (cl_prop[i].name == prop_name) + return cl_prop[i]; + // if not found, returns an empty DbDatum + return Tango::DbDatum(prop_name); +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::get_default_device_property() + * Description: Return the default value for device property. + */ +//-------------------------------------------------------- +Tango::DbDatum PLCRack3Class::get_default_device_property(std::string &prop_name) +{ + for (unsigned int i=0 ; i<dev_def_prop.size() ; i++) + if (dev_def_prop[i].name == prop_name) + return dev_def_prop[i]; + // if not found, return an empty DbDatum + return Tango::DbDatum(prop_name); +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::get_default_class_property() + * Description: Return the default value for class property. + */ +//-------------------------------------------------------- +Tango::DbDatum PLCRack3Class::get_default_class_property(std::string &prop_name) +{ + for (unsigned int i=0 ; i<cl_def_prop.size() ; i++) + if (cl_def_prop[i].name == prop_name) + return cl_def_prop[i]; + // if not found, return an empty DbDatum + return Tango::DbDatum(prop_name); +} + + +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::set_default_property() + * Description: Set default property (class and device) for wizard. + * For each property, add to wizard property name and description. + * If default value has been set, add it to wizard property and + * store it in a DbDatum. + */ +//-------------------------------------------------------- +void PLCRack3Class::set_default_property() +{ + std::string prop_name; + std::string prop_desc; + std::string prop_def; + std::vector<std::string> vect_data; + + // Set Default Class Properties + + // Set Default device Properties +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::write_class_property() + * Description: Set class description fields as property in database + */ +//-------------------------------------------------------- +void PLCRack3Class::write_class_property() +{ + // First time, check if database used + if (Tango::Util::_UseDb == false) + return; + + Tango::DbData data; + std::string classname = get_name(); + std::string header; + + // Put title + Tango::DbDatum title("ProjectTitle"); + std::string str_title("PLCRack3"); + title << str_title; + data.push_back(title); + + // Put Description + Tango::DbDatum description("Description"); + std::vector<std::string> str_desc; + str_desc.push_back("PLC Rack Triplo"); + description << str_desc; + data.push_back(description); + + // Put inheritance + Tango::DbDatum inher_datum("InheritedFrom"); + std::vector<std::string> inheritance; + inheritance.push_back("TANGO_BASE_CLASS"); + inher_datum << inheritance; + data.push_back(inher_datum); + + // Call database and and values + get_db_class()->put_property(data); +} + +//=================================================================== +// Factory methods +//=================================================================== + +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::device_factory() + * Description: Create the device object(s) + * and store them in the device list + */ +//-------------------------------------------------------- +void PLCRack3Class::device_factory(const Tango::DevVarStringArray *devlist_ptr) +{ + /*----- PROTECTED REGION ID(PLCRack3Class::device_factory_before) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::device_factory_before + + // Create devices and add it into the device list + for (unsigned long i=0 ; i<devlist_ptr->length() ; i++) + { + TANGO_LOG_DEBUG << "Device name : " << (*devlist_ptr)[i].in() << std::endl; + device_list.push_back(new PLCRack3(this, (*devlist_ptr)[i])); + } + + // Manage dynamic attributes if any + erase_dynamic_attributes(devlist_ptr, get_class_attr()->get_attr_list()); + + // Export devices to the outside world + for (unsigned long i=1 ; i<=devlist_ptr->length() ; i++) + { + // Add dynamic attributes if any + PLCRack3 *dev = static_cast<PLCRack3 *>(device_list[device_list.size()-i]); + dev->add_dynamic_attributes(); + + // Check before if database used. + if ((Tango::Util::_UseDb == true) && (Tango::Util::_FileDb == false)) + export_device(dev); + else + export_device(dev, dev->get_name().c_str()); + } + + /*----- PROTECTED REGION ID(PLCRack3Class::device_factory_after) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::device_factory_after +} +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::attribute_factory() + * Description: Create the attribute object(s) + * and store them in the attribute list + */ +//-------------------------------------------------------- +void PLCRack3Class::attribute_factory(std::vector<Tango::Attr *> &att_list) +{ + /*----- PROTECTED REGION ID(PLCRack3Class::attribute_factory_before) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::attribute_factory_before + // Call atribute_factory for inherited class + Socket2Client_ns::Socket2ClientClass::attribute_factory(att_list); + + // Attribute : sezione2Temp + sezione2TempAttrib *sezione2temp = new sezione2TempAttrib(); + Tango::UserDefaultAttrProp sezione2temp_prop; + // description not set for sezione2Temp + // label not set for sezione2Temp + // unit not set for sezione2Temp + // standard_unit not set for sezione2Temp + // display_unit not set for sezione2Temp + // format not set for sezione2Temp + // max_value not set for sezione2Temp + // min_value not set for sezione2Temp + // max_alarm not set for sezione2Temp + // min_alarm not set for sezione2Temp + // max_warning not set for sezione2Temp + // min_warning not set for sezione2Temp + // delta_t not set for sezione2Temp + // delta_val not set for sezione2Temp + sezione2temp->set_default_properties(sezione2temp_prop); + // Not Polled + sezione2temp->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione2temp); + + // Attribute : sezione1Temp + sezione1TempAttrib *sezione1temp = new sezione1TempAttrib(); + Tango::UserDefaultAttrProp sezione1temp_prop; + // description not set for sezione1Temp + // label not set for sezione1Temp + // unit not set for sezione1Temp + // standard_unit not set for sezione1Temp + // display_unit not set for sezione1Temp + // format not set for sezione1Temp + // max_value not set for sezione1Temp + // min_value not set for sezione1Temp + // max_alarm not set for sezione1Temp + // min_alarm not set for sezione1Temp + // max_warning not set for sezione1Temp + // min_warning not set for sezione1Temp + // delta_t not set for sezione1Temp + // delta_val not set for sezione1Temp + sezione1temp->set_default_properties(sezione1temp_prop); + // Not Polled + sezione1temp->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione1temp); + + // Attribute : buncherTemp + buncherTempAttrib *bunchertemp = new buncherTempAttrib(); + Tango::UserDefaultAttrProp bunchertemp_prop; + // description not set for buncherTemp + // label not set for buncherTemp + // unit not set for buncherTemp + // standard_unit not set for buncherTemp + // display_unit not set for buncherTemp + // format not set for buncherTemp + // max_value not set for buncherTemp + // min_value not set for buncherTemp + // max_alarm not set for buncherTemp + // min_alarm not set for buncherTemp + // max_warning not set for buncherTemp + // min_warning not set for buncherTemp + // delta_t not set for buncherTemp + // delta_val not set for buncherTemp + bunchertemp->set_default_properties(bunchertemp_prop); + // Not Polled + bunchertemp->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(bunchertemp); + + // Attribute : sezione2State + sezione2StateAttrib *sezione2state = new sezione2StateAttrib(); + Tango::UserDefaultAttrProp sezione2state_prop; + // description not set for sezione2State + // label not set for sezione2State + // unit not set for sezione2State + // standard_unit not set for sezione2State + // display_unit not set for sezione2State + // format not set for sezione2State + // max_value not set for sezione2State + // min_value not set for sezione2State + // max_alarm not set for sezione2State + // min_alarm not set for sezione2State + // max_warning not set for sezione2State + // min_warning not set for sezione2State + // delta_t not set for sezione2State + // delta_val not set for sezione2State + sezione2state->set_default_properties(sezione2state_prop); + // Not Polled + sezione2state->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione2state); + + // Attribute : sezione1State + sezione1StateAttrib *sezione1state = new sezione1StateAttrib(); + Tango::UserDefaultAttrProp sezione1state_prop; + // description not set for sezione1State + // label not set for sezione1State + // unit not set for sezione1State + // standard_unit not set for sezione1State + // display_unit not set for sezione1State + // format not set for sezione1State + // max_value not set for sezione1State + // min_value not set for sezione1State + // max_alarm not set for sezione1State + // min_alarm not set for sezione1State + // max_warning not set for sezione1State + // min_warning not set for sezione1State + // delta_t not set for sezione1State + // delta_val not set for sezione1State + sezione1state->set_default_properties(sezione1state_prop); + // Not Polled + sezione1state->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione1state); + + // Attribute : buncherState + buncherStateAttrib *buncherstate = new buncherStateAttrib(); + Tango::UserDefaultAttrProp buncherstate_prop; + // description not set for buncherState + // label not set for buncherState + // unit not set for buncherState + // standard_unit not set for buncherState + // display_unit not set for buncherState + // format not set for buncherState + // max_value not set for buncherState + // min_value not set for buncherState + // max_alarm not set for buncherState + // min_alarm not set for buncherState + // max_warning not set for buncherState + // min_warning not set for buncherState + // delta_t not set for buncherState + // delta_val not set for buncherState + buncherstate->set_default_properties(buncherstate_prop); + // Not Polled + buncherstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(buncherstate); + + // Attribute : sezione2FSHighState + sezione2FSHighStateAttrib *sezione2fshighstate = new sezione2FSHighStateAttrib(); + Tango::UserDefaultAttrProp sezione2fshighstate_prop; + // description not set for sezione2FSHighState + // label not set for sezione2FSHighState + // unit not set for sezione2FSHighState + // standard_unit not set for sezione2FSHighState + // display_unit not set for sezione2FSHighState + // format not set for sezione2FSHighState + // max_value not set for sezione2FSHighState + // min_value not set for sezione2FSHighState + // max_alarm not set for sezione2FSHighState + // min_alarm not set for sezione2FSHighState + // max_warning not set for sezione2FSHighState + // min_warning not set for sezione2FSHighState + // delta_t not set for sezione2FSHighState + // delta_val not set for sezione2FSHighState + sezione2fshighstate->set_default_properties(sezione2fshighstate_prop); + // Not Polled + sezione2fshighstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione2fshighstate); + + // Attribute : sezione2TSState + sezione2TSStateAttrib *sezione2tsstate = new sezione2TSStateAttrib(); + Tango::UserDefaultAttrProp sezione2tsstate_prop; + // description not set for sezione2TSState + // label not set for sezione2TSState + // unit not set for sezione2TSState + // standard_unit not set for sezione2TSState + // display_unit not set for sezione2TSState + // format not set for sezione2TSState + // max_value not set for sezione2TSState + // min_value not set for sezione2TSState + // max_alarm not set for sezione2TSState + // min_alarm not set for sezione2TSState + // max_warning not set for sezione2TSState + // min_warning not set for sezione2TSState + // delta_t not set for sezione2TSState + // delta_val not set for sezione2TSState + sezione2tsstate->set_default_properties(sezione2tsstate_prop); + // Not Polled + sezione2tsstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione2tsstate); + + // Attribute : sezione1FSHighState + sezione1FSHighStateAttrib *sezione1fshighstate = new sezione1FSHighStateAttrib(); + Tango::UserDefaultAttrProp sezione1fshighstate_prop; + // description not set for sezione1FSHighState + // label not set for sezione1FSHighState + // unit not set for sezione1FSHighState + // standard_unit not set for sezione1FSHighState + // display_unit not set for sezione1FSHighState + // format not set for sezione1FSHighState + // max_value not set for sezione1FSHighState + // min_value not set for sezione1FSHighState + // max_alarm not set for sezione1FSHighState + // min_alarm not set for sezione1FSHighState + // max_warning not set for sezione1FSHighState + // min_warning not set for sezione1FSHighState + // delta_t not set for sezione1FSHighState + // delta_val not set for sezione1FSHighState + sezione1fshighstate->set_default_properties(sezione1fshighstate_prop); + // Not Polled + sezione1fshighstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione1fshighstate); + + // Attribute : sezione1TSState + sezione1TSStateAttrib *sezione1tsstate = new sezione1TSStateAttrib(); + Tango::UserDefaultAttrProp sezione1tsstate_prop; + // description not set for sezione1TSState + // label not set for sezione1TSState + // unit not set for sezione1TSState + // standard_unit not set for sezione1TSState + // display_unit not set for sezione1TSState + // format not set for sezione1TSState + // max_value not set for sezione1TSState + // min_value not set for sezione1TSState + // max_alarm not set for sezione1TSState + // min_alarm not set for sezione1TSState + // max_warning not set for sezione1TSState + // min_warning not set for sezione1TSState + // delta_t not set for sezione1TSState + // delta_val not set for sezione1TSState + sezione1tsstate->set_default_properties(sezione1tsstate_prop); + // Not Polled + sezione1tsstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione1tsstate); + + // Attribute : buncherFSHighState + buncherFSHighStateAttrib *buncherfshighstate = new buncherFSHighStateAttrib(); + Tango::UserDefaultAttrProp buncherfshighstate_prop; + // description not set for buncherFSHighState + // label not set for buncherFSHighState + // unit not set for buncherFSHighState + // standard_unit not set for buncherFSHighState + // display_unit not set for buncherFSHighState + // format not set for buncherFSHighState + // max_value not set for buncherFSHighState + // min_value not set for buncherFSHighState + // max_alarm not set for buncherFSHighState + // min_alarm not set for buncherFSHighState + // max_warning not set for buncherFSHighState + // min_warning not set for buncherFSHighState + // delta_t not set for buncherFSHighState + // delta_val not set for buncherFSHighState + buncherfshighstate->set_default_properties(buncherfshighstate_prop); + // Not Polled + buncherfshighstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(buncherfshighstate); + + // Attribute : buncherTSState + buncherTSStateAttrib *bunchertsstate = new buncherTSStateAttrib(); + Tango::UserDefaultAttrProp bunchertsstate_prop; + // description not set for buncherTSState + // label not set for buncherTSState + // unit not set for buncherTSState + // standard_unit not set for buncherTSState + // display_unit not set for buncherTSState + // format not set for buncherTSState + // max_value not set for buncherTSState + // min_value not set for buncherTSState + // max_alarm not set for buncherTSState + // min_alarm not set for buncherTSState + // max_warning not set for buncherTSState + // min_warning not set for buncherTSState + // delta_t not set for buncherTSState + // delta_val not set for buncherTSState + bunchertsstate->set_default_properties(bunchertsstate_prop); + // Not Polled + bunchertsstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(bunchertsstate); + + // Attribute : sezione2FSLowState + sezione2FSLowStateAttrib *sezione2fslowstate = new sezione2FSLowStateAttrib(); + Tango::UserDefaultAttrProp sezione2fslowstate_prop; + // description not set for sezione2FSLowState + // label not set for sezione2FSLowState + // unit not set for sezione2FSLowState + // standard_unit not set for sezione2FSLowState + // display_unit not set for sezione2FSLowState + // format not set for sezione2FSLowState + // max_value not set for sezione2FSLowState + // min_value not set for sezione2FSLowState + // max_alarm not set for sezione2FSLowState + // min_alarm not set for sezione2FSLowState + // max_warning not set for sezione2FSLowState + // min_warning not set for sezione2FSLowState + // delta_t not set for sezione2FSLowState + // delta_val not set for sezione2FSLowState + sezione2fslowstate->set_default_properties(sezione2fslowstate_prop); + // Not Polled + sezione2fslowstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione2fslowstate); + + // Attribute : sezione1FSLowState + sezione1FSLowStateAttrib *sezione1fslowstate = new sezione1FSLowStateAttrib(); + Tango::UserDefaultAttrProp sezione1fslowstate_prop; + // description not set for sezione1FSLowState + // label not set for sezione1FSLowState + // unit not set for sezione1FSLowState + // standard_unit not set for sezione1FSLowState + // display_unit not set for sezione1FSLowState + // format not set for sezione1FSLowState + // max_value not set for sezione1FSLowState + // min_value not set for sezione1FSLowState + // max_alarm not set for sezione1FSLowState + // min_alarm not set for sezione1FSLowState + // max_warning not set for sezione1FSLowState + // min_warning not set for sezione1FSLowState + // delta_t not set for sezione1FSLowState + // delta_val not set for sezione1FSLowState + sezione1fslowstate->set_default_properties(sezione1fslowstate_prop); + // Not Polled + sezione1fslowstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(sezione1fslowstate); + + // Attribute : buncherFSLowState + buncherFSLowStateAttrib *buncherfslowstate = new buncherFSLowStateAttrib(); + Tango::UserDefaultAttrProp buncherfslowstate_prop; + // description not set for buncherFSLowState + // label not set for buncherFSLowState + // unit not set for buncherFSLowState + // standard_unit not set for buncherFSLowState + // display_unit not set for buncherFSLowState + // format not set for buncherFSLowState + // max_value not set for buncherFSLowState + // min_value not set for buncherFSLowState + // max_alarm not set for buncherFSLowState + // min_alarm not set for buncherFSLowState + // max_warning not set for buncherFSLowState + // min_warning not set for buncherFSLowState + // delta_t not set for buncherFSLowState + // delta_val not set for buncherFSLowState + buncherfslowstate->set_default_properties(buncherfslowstate_prop); + // Not Polled + buncherfslowstate->set_disp_level(Tango::OPERATOR); + // Not Memorized + att_list.push_back(buncherfslowstate); + + + // Create a list of static attributes + create_static_attribute_list(get_class_attr()->get_attr_list()); + /*----- PROTECTED REGION ID(PLCRack3Class::attribute_factory_after) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::attribute_factory_after +} +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::pipe_factory() + * Description: Create the pipe object(s) + * and store them in the pipe list + */ +//-------------------------------------------------------- +void PLCRack3Class::pipe_factory() +{ + /*----- PROTECTED REGION ID(PLCRack3Class::pipe_factory_before) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::pipe_factory_before + /*----- PROTECTED REGION ID(PLCRack3Class::pipe_factory_after) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::pipe_factory_after +} +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::command_factory() + * Description: Create the command object(s) + * and store them in the command list + */ +//-------------------------------------------------------- +void PLCRack3Class::command_factory() +{ + /*----- PROTECTED REGION ID(PLCRack3Class::command_factory_before) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::command_factory_before + // Call command_factory for inherited class + Socket2Client_ns::Socket2ClientClass::command_factory(); + + + + /*----- PROTECTED REGION ID(PLCRack3Class::command_factory_after) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::command_factory_after +} + +//=================================================================== +// Dynamic attributes related methods +//=================================================================== + +//-------------------------------------------------------- +/** + * method : PLCRack3Class::create_static_attribute_list + * description : Create the a list of static attributes + * + * @param att_list the created attribute list + */ +//-------------------------------------------------------- +void PLCRack3Class::create_static_attribute_list(std::vector<Tango::Attr *> &att_list) +{ + for (unsigned long i=0 ; i<att_list.size() ; i++) + { + std::string att_name(att_list[i]->get_name()); + transform(att_name.begin(), att_name.end(), att_name.begin(), ::tolower); + defaultAttList.push_back(att_name); + } + + TANGO_LOG_INFO << defaultAttList.size() << " attributes in default list" << std::endl; + + /*----- PROTECTED REGION ID(PLCRack3Class::create_static_att_list) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::create_static_att_list +} + + +//-------------------------------------------------------- +/** + * method : PLCRack3Class::erase_dynamic_attributes + * description : delete the dynamic attributes if any. + * + * @param devlist_ptr the device list pointer + * @param list of all attributes + */ +//-------------------------------------------------------- +void PLCRack3Class::erase_dynamic_attributes(const Tango::DevVarStringArray *devlist_ptr, std::vector<Tango::Attr *> &att_list) +{ + Tango::Util *tg = Tango::Util::instance(); + + for (unsigned long i=0 ; i<devlist_ptr->length() ; i++) + { + Tango::DeviceImpl *dev_impl = tg->get_device_by_name(((std::string)(*devlist_ptr)[i]).c_str()); + PLCRack3 *dev = static_cast<PLCRack3 *> (dev_impl); + + std::vector<Tango::Attribute *> &dev_att_list = dev->get_device_attr()->get_attribute_list(); + std::vector<Tango::Attribute *>::iterator ite_att; + for (ite_att=dev_att_list.begin() ; ite_att != dev_att_list.end() ; ++ite_att) + { + std::string att_name((*ite_att)->get_name_lower()); + if ((att_name == "state") || (att_name == "status")) + continue; + std::vector<std::string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name); + if (ite_str == defaultAttList.end()) + { + TANGO_LOG_INFO << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << std::endl; + Tango::Attribute &att = dev->get_device_attr()->get_attr_by_name(att_name.c_str()); + dev->remove_attribute(att_list[att.get_attr_idx()], true, false); + --ite_att; + } + } + } + /*----- PROTECTED REGION ID(PLCRack3Class::erase_dynamic_attributes) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::erase_dynamic_attributes +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3Class::get_attr_object_by_name() + * Description: returns Tango::Attr * object found by name + */ +//-------------------------------------------------------- +Tango::Attr *PLCRack3Class::get_attr_object_by_name(std::vector<Tango::Attr *> &att_list, std::string attname) +{ + std::vector<Tango::Attr *>::iterator it; + for (it=att_list.begin() ; it<att_list.end() ; ++it) + if ((*it)->get_name()==attname) + return (*it); + // Attr does not exist + return NULL; +} + + +/*----- PROTECTED REGION ID(PLCRack3Class::Additional Methods) ENABLED START -----*/ +/* clang-format on */ +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3Class::Additional Methods +} // namespace diff --git a/src/PLCRack3Class.h b/src/PLCRack3Class.h new file mode 100644 index 0000000..aad7a80 --- /dev/null +++ b/src/PLCRack3Class.h @@ -0,0 +1,313 @@ +/*----- PROTECTED REGION ID(PLCRack3Class.h) ENABLED START -----*/ +/* clang-format on */ +//============================================================================= +// +// file : PLCRack3Class.h +// +// description : Include for the PLCRack3 root class. +// This class is the singleton class for +// the PLCRack3 device class. +// It contains all properties and methods which the +// PLCRack3 requires only once e.g. the commands. +// +// project : PLCRack3 +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or 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 option) any later version. +// +// Tango 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= + + +#ifndef PLCRack3Class_H +#define PLCRack3Class_H + +#include <tango.h> +#include <Socket2ClientClass.h> +#include "PLCRack3.h" + +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3Class.h + + +namespace PLCRack3_ns +{ +/*----- PROTECTED REGION ID(PLCRack3Class::classes for dynamic creation) ENABLED START -----*/ +/* clang-format on */ + +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3Class::classes for dynamic creation + +//========================================= +// Define classes for attributes +//========================================= +// Attribute sezione2Temp class definition +class sezione2TempAttrib: public Tango::Attr +{ +public: + sezione2TempAttrib():Attr("sezione2Temp", + Tango::DEV_DOUBLE, Tango::READ) {} + ~sezione2TempAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione2Temp(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione2Temp_allowed(ty);} +}; + +// Attribute sezione1Temp class definition +class sezione1TempAttrib: public Tango::Attr +{ +public: + sezione1TempAttrib():Attr("sezione1Temp", + Tango::DEV_DOUBLE, Tango::READ) {} + ~sezione1TempAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione1Temp(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione1Temp_allowed(ty);} +}; + +// Attribute buncherTemp class definition +class buncherTempAttrib: public Tango::Attr +{ +public: + buncherTempAttrib():Attr("buncherTemp", + Tango::DEV_DOUBLE, Tango::READ) {} + ~buncherTempAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_buncherTemp(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_buncherTemp_allowed(ty);} +}; + +// Attribute sezione2State class definition +class sezione2StateAttrib: public Tango::Attr +{ +public: + sezione2StateAttrib():Attr("sezione2State", + Tango::DEV_BOOLEAN, Tango::READ_WRITE) {} + ~sezione2StateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione2State(att);} + virtual void write(Tango::DeviceImpl *dev,Tango::WAttribute &att) + {(static_cast<PLCRack3 *>(dev))->write_sezione2State(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione2State_allowed(ty);} +}; + +// Attribute sezione1State class definition +class sezione1StateAttrib: public Tango::Attr +{ +public: + sezione1StateAttrib():Attr("sezione1State", + Tango::DEV_BOOLEAN, Tango::READ_WRITE) {} + ~sezione1StateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione1State(att);} + virtual void write(Tango::DeviceImpl *dev,Tango::WAttribute &att) + {(static_cast<PLCRack3 *>(dev))->write_sezione1State(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione1State_allowed(ty);} +}; + +// Attribute buncherState class definition +class buncherStateAttrib: public Tango::Attr +{ +public: + buncherStateAttrib():Attr("buncherState", + Tango::DEV_BOOLEAN, Tango::READ_WRITE) {} + ~buncherStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_buncherState(att);} + virtual void write(Tango::DeviceImpl *dev,Tango::WAttribute &att) + {(static_cast<PLCRack3 *>(dev))->write_buncherState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_buncherState_allowed(ty);} +}; + +// Attribute sezione2FSHighState class definition +class sezione2FSHighStateAttrib: public Tango::Attr +{ +public: + sezione2FSHighStateAttrib():Attr("sezione2FSHighState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~sezione2FSHighStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione2FSHighState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione2FSHighState_allowed(ty);} +}; + +// Attribute sezione2TSState class definition +class sezione2TSStateAttrib: public Tango::Attr +{ +public: + sezione2TSStateAttrib():Attr("sezione2TSState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~sezione2TSStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione2TSState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione2TSState_allowed(ty);} +}; + +// Attribute sezione1FSHighState class definition +class sezione1FSHighStateAttrib: public Tango::Attr +{ +public: + sezione1FSHighStateAttrib():Attr("sezione1FSHighState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~sezione1FSHighStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione1FSHighState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione1FSHighState_allowed(ty);} +}; + +// Attribute sezione1TSState class definition +class sezione1TSStateAttrib: public Tango::Attr +{ +public: + sezione1TSStateAttrib():Attr("sezione1TSState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~sezione1TSStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione1TSState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione1TSState_allowed(ty);} +}; + +// Attribute buncherFSHighState class definition +class buncherFSHighStateAttrib: public Tango::Attr +{ +public: + buncherFSHighStateAttrib():Attr("buncherFSHighState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~buncherFSHighStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_buncherFSHighState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_buncherFSHighState_allowed(ty);} +}; + +// Attribute buncherTSState class definition +class buncherTSStateAttrib: public Tango::Attr +{ +public: + buncherTSStateAttrib():Attr("buncherTSState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~buncherTSStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_buncherTSState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_buncherTSState_allowed(ty);} +}; + +// Attribute sezione2FSLowState class definition +class sezione2FSLowStateAttrib: public Tango::Attr +{ +public: + sezione2FSLowStateAttrib():Attr("sezione2FSLowState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~sezione2FSLowStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione2FSLowState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione2FSLowState_allowed(ty);} +}; + +// Attribute sezione1FSLowState class definition +class sezione1FSLowStateAttrib: public Tango::Attr +{ +public: + sezione1FSLowStateAttrib():Attr("sezione1FSLowState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~sezione1FSLowStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_sezione1FSLowState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_sezione1FSLowState_allowed(ty);} +}; + +// Attribute buncherFSLowState class definition +class buncherFSLowStateAttrib: public Tango::Attr +{ +public: + buncherFSLowStateAttrib():Attr("buncherFSLowState", + Tango::DEV_BOOLEAN, Tango::READ) {} + ~buncherFSLowStateAttrib() {} + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast<PLCRack3 *>(dev))->read_buncherFSLowState(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast<PLCRack3 *>(dev))->is_buncherFSLowState_allowed(ty);} +}; + + +/** + * The PLCRack3Class singleton definition + */ + +#ifdef _TG_WINDOWS_ +class __declspec(dllexport) PLCRack3Class : public Socket2Client_ns::Socket2ClientClass +#else +class PLCRack3Class : public Socket2Client_ns::Socket2ClientClass +#endif +{ + /*----- PROTECTED REGION ID(PLCRack3Class::Additional DServer data members) ENABLED START -----*/ + /* clang-format on */ + // Add your own code + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3Class::Additional DServer data members + + public: + // write class properties data members + Tango::DbData cl_prop; + Tango::DbData cl_def_prop; + Tango::DbData dev_def_prop; + // Method prototypes + static PLCRack3Class *init(const char *); + static PLCRack3Class *instance(); + ~PLCRack3Class(); + Tango::DbDatum get_class_property(std::string &); + Tango::DbDatum get_default_device_property(std::string &); + Tango::DbDatum get_default_class_property(std::string &); + + protected: + PLCRack3Class(std::string &); + static PLCRack3Class *_instance; + void command_factory(); + void attribute_factory(std::vector<Tango::Attr *> &); + void pipe_factory(); + void write_class_property(); + void set_default_property(); + void get_class_property(); + std::string get_cvstag(); + std::string get_cvsroot(); + + private: + void device_factory(TANGO_UNUSED(const Tango::DevVarStringArray *)); + void create_static_attribute_list(std::vector<Tango::Attr *> &); + void erase_dynamic_attributes(const Tango::DevVarStringArray *,std::vector<Tango::Attr *> &); + std::vector<std::string> defaultAttList; + Tango::Attr *get_attr_object_by_name(std::vector<Tango::Attr *> &att_list, std::string attname); +}; + +} // End of namespace + +#endif // PLCRack3_H diff --git a/src/PLCRack3StateMachine.cpp b/src/PLCRack3StateMachine.cpp new file mode 100644 index 0000000..6450439 --- /dev/null +++ b/src/PLCRack3StateMachine.cpp @@ -0,0 +1,331 @@ +/*----- PROTECTED REGION ID(PLCRack3StateMachine.cpp) ENABLED START -----*/ +/* clang-format on */ +//============================================================================= +// +// file : PLCRack3StateMachine.cpp +// +// description : State machine file for the PLCRack3 class +// +// project : PLCRack3 +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or 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 option) any later version. +// +// Tango 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= + +#include "PLCRack3.h" + +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::PLCRack3StateMachine.cpp + +//================================================================ +// States | Description +//================================================================ + + +namespace PLCRack3_ns +{ +//================================================= +// Attributes Allowed Methods +//================================================= + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione2Temp_allowed() + * Description: Execution allowed for sezione2Temp attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione2Temp_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione2Temp attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione2TempStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione2TempStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione1Temp_allowed() + * Description: Execution allowed for sezione1Temp attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione1Temp_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione1Temp attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione1TempStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione1TempStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_buncherTemp_allowed() + * Description: Execution allowed for buncherTemp attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_buncherTemp_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for buncherTemp attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::buncherTempStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::buncherTempStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione2State_allowed() + * Description: Execution allowed for sezione2State attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione2State_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + // Not any excluded states for sezione2State attribute in Write access. + /*----- PROTECTED REGION ID(PLCRack3::sezione2StateStateAllowed_WRITE) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione2StateStateAllowed_WRITE + + // Not any excluded states for sezione2State attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione2StateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione2StateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione1State_allowed() + * Description: Execution allowed for sezione1State attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione1State_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + // Not any excluded states for sezione1State attribute in Write access. + /*----- PROTECTED REGION ID(PLCRack3::sezione1StateStateAllowed_WRITE) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione1StateStateAllowed_WRITE + + // Not any excluded states for sezione1State attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione1StateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione1StateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_buncherState_allowed() + * Description: Execution allowed for buncherState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_buncherState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + // Not any excluded states for buncherState attribute in Write access. + /*----- PROTECTED REGION ID(PLCRack3::buncherStateStateAllowed_WRITE) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::buncherStateStateAllowed_WRITE + + // Not any excluded states for buncherState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::buncherStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::buncherStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione2FSHighState_allowed() + * Description: Execution allowed for sezione2FSHighState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione2FSHighState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione2FSHighState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione2FSHighStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione2FSHighStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione2TSState_allowed() + * Description: Execution allowed for sezione2TSState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione2TSState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione2TSState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione2TSStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione2TSStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione1FSHighState_allowed() + * Description: Execution allowed for sezione1FSHighState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione1FSHighState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione1FSHighState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione1FSHighStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione1FSHighStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione1TSState_allowed() + * Description: Execution allowed for sezione1TSState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione1TSState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione1TSState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione1TSStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione1TSStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_buncherFSHighState_allowed() + * Description: Execution allowed for buncherFSHighState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_buncherFSHighState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for buncherFSHighState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::buncherFSHighStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::buncherFSHighStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_buncherTSState_allowed() + * Description: Execution allowed for buncherTSState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_buncherTSState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for buncherTSState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::buncherTSStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::buncherTSStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione2FSLowState_allowed() + * Description: Execution allowed for sezione2FSLowState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione2FSLowState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione2FSLowState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione2FSLowStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione2FSLowStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_sezione1FSLowState_allowed() + * Description: Execution allowed for sezione1FSLowState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_sezione1FSLowState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for sezione1FSLowState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::sezione1FSLowStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::sezione1FSLowStateStateAllowed_READ + return true; +} + +//-------------------------------------------------------- +/** + * Method : PLCRack3::is_buncherFSLowState_allowed() + * Description: Execution allowed for buncherFSLowState attribute + */ +//-------------------------------------------------------- +bool PLCRack3::is_buncherFSLowState_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + + // Not any excluded states for buncherFSLowState attribute in read access. + /*----- PROTECTED REGION ID(PLCRack3::buncherFSLowStateStateAllowed_READ) ENABLED START -----*/ + /* clang-format on */ + /* clang-format off */ + /*----- PROTECTED REGION END -----*/ // PLCRack3::buncherFSLowStateStateAllowed_READ + return true; +} + + +//================================================= +// Commands Allowed Methods +//================================================= + + +/*----- PROTECTED REGION ID(PLCRack3::PLCRack3StateAllowed.AdditionalMethods) ENABLED START -----*/ +/* clang-format on */ +// Additional Methods +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::PLCRack3StateAllowed.AdditionalMethods + +} // End of namespace diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..271851c --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,88 @@ +/*----- PROTECTED REGION ID(PLCRack3::main.cpp) ENABLED START -----*/ +/* clang-format on */ +//============================================================================= +// +// file : main.cpp +// +// description : C++ source for the PLCRack3 device server main. +// The main rule is to initialize (and create) the Tango +// system and to create the DServerClass singleton. +// The main should be the same for every Tango device server. +// +// project : PLCRack3 +// +// This file is part of Tango device class. +// +// Tango is free software: you can redistribute it and/or 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 option) any later version. +// +// Tango 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Tango. If not, see <http://www.gnu.org/licenses/>. +// +// +// +//============================================================================= +// This file is generated by POGO +// (Program Obviously used to Generate tango Object) +//============================================================================= +#include <tango.h> + +// Check if crash reporting is used. +#if defined(ENABLE_CRASH_REPORT) +# include <crashreporting/crash_report.h> +#else +# define DECLARE_CRASH_HANDLER +# define INSTALL_CRASH_HANDLER +#endif + +DECLARE_CRASH_HANDLER + +int main(int argc,char *argv[]) +{ + INSTALL_CRASH_HANDLER + Tango::Util *tg = nullptr; + try + { + // Initialize the device server + //---------------------------------------- + tg = Tango::Util::init(argc,argv); + + // Create the device server singleton + // which will create everything + //---------------------------------------- + tg->server_init(false); + + // Run the endless loop + //---------------------------------------- + std::cout << "Ready to accept request" << std::endl; + tg->server_run(); + } + catch (std::bad_alloc &) + { + std::cout << "Can't allocate memory to store device object !!!" << std::endl; + std::cout << "Exiting" << std::endl; + } + catch (CORBA::Exception &e) + { + Tango::Except::print_exception(e); + + std::cout << "Received a CORBA_Exception" << std::endl; + std::cout << "Exiting" << std::endl; + } + + if(tg) + { + tg->server_cleanup(); + } + return(0); +} + +/* clang-format off */ +/*----- PROTECTED REGION END -----*/ // PLCRack3::main.cpp diff --git a/src/plcsrvthread.cpp b/src/plcsrvthread.cpp new file mode 100644 index 0000000..a0953a2 --- /dev/null +++ b/src/plcsrvthread.cpp @@ -0,0 +1,406 @@ +/* + * plcsrvthread.cpp + * + * 2009/07/16 - SF: first release + * + * + */ + +#include "plcsrvthread.h" +#include <iomanip> //used for debug dump of db +#include <netdb.h> + +namespace PLCRack3_ns{ + + +/* + * plcsrvthread::run() + * Run + */ +void plcsrvthread::run(void *) +{ + DEBUG_STREAM << "plcsrvthread::run() entering..." << endl; + int pausemicro = 3000000; + server_started=0; + push_counter = 0; + allow_push = true; + + + buf = new char[2*BUF_LEN]; + while (!t_PLCRack3->abortflag) { + if(server_started==0) + { + Srv_Prepare(); + } + else + { + t_PLCRack3->set_state(Tango::FAULT); + t_PLCRack3->set_status("srv not connected"); + } + + usleep(pausemicro); + DEBUG_STREAM << "plcsrvthread::run() trying to reconnect" << endl; + } + delete [] buf; +} + + + + +void plcsrvthread::Srv_Prepare(void) +{ + DEBUG_STREAM << "plcsrvthread::"<<__func__<<": entering..." << endl; + char *save_buf_ptr = &buf[0];; + timeval t_now; + gettimeofday(&last_read, NULL); + while (!t_PLCRack3->abortflag) + { + bool connection_ok = false; + + server_started=1; //fake + Tango::DevState dp_state=Tango::FAULT; + try + { + dp_state = t_PLCRack3->socket_get_state(); + if(dp_state == Tango::ON) + connection_ok = true; + } + catch(Tango::DevFailed &e) + { + INFO_STREAM << __func__ << ": error reading socket state="<<e.errors[0].desc; + sleep(1); + } + + if(connection_ok) + {//connection established + DEBUG_STREAM<<"plcsrvthread::Srv_Prepare() connection ok"<<endl; + errcount =0; + first_mesg = true; + cnt = 0; + buf = save_buf_ptr; + memset (buf,0,2*BUF_LEN); + + do + { + gettimeofday(&t_now, NULL); + double diff_s = t_now.tv_sec - last_read.tv_sec; + if(diff_s > 30) + { + t_PLCRack3->set_state(Tango::ALARM); + t_PLCRack3->set_status("Timeout waiting PLC data"); + } + + while(cnt > 0) + { + header_t *head; + head = reinterpret_cast<header_t *>(&buf[0]); + uint16_t btype = head->db_number; + btype = ntohs(btype); + if(btype == 0) + { + cnt--; + buf++; + DEBUG_STREAM << "plcsrvthread::run() looking for header, now " << cnt << " in buffer"<<endl; + if(cnt == 0) + { + buf = save_buf_ptr; + memset (buf,0,2*BUF_LEN); + INFO_STREAM << __func__ << ": " << cnt << " unknown bytes in buffer, type="<<btype<<", emptying"; + } + } + else + { + break; + } + } + + //DEBUG_STREAM << "plcsrvthread::Srv_Prepare()going to read from sock" << endl; + try + { + Tango::DevLong count=t_PLCRack3->input_length(); + if(count > 0) + { + if(count+cnt > BUF_LEN) + count = BUF_LEN-cnt; + vector<unsigned char> dtr; + t_PLCRack3->read(count, dtr); + for (unsigned int i=0; i<dtr.size(); ++i) + { + buf[i] = dtr[i]; + } + gettimeofday(&last_read, NULL); + INFO_STREAM << __func__ << ": read " << count << " now " << cnt+count << " in buffer" << endl; + } + else + { + timespec time_to_sleep; + time_to_sleep.tv_sec=0; + //time_to_sleep.tv_nsec= 0.5 * 1000000L;//0.5ms + //time_to_sleep.tv_nsec= 10 * 1000000L;//100ms + time_to_sleep.tv_nsec= 100 * 1000000L;//100ms + //time_to_sleep.tv_nsec= 500 * 1000000L;//500ms + nanosleep(&time_to_sleep, NULL); + } + cnt += count; + if(t_PLCRack3->get_state() != Tango::RUNNING) + { + t_PLCRack3->set_status("PLC OK"); + t_PLCRack3->set_state(Tango::RUNNING); + } + } + catch(Tango::DevFailed &e) + { + stringstream tmp; + tmp << "Error reading " << e.errors[0].desc; + INFO_STREAM << __func__ << ": " << tmp.str(); + cnt = -1; + t_PLCRack3->set_state(Tango::FAULT); + t_PLCRack3->set_status(tmp.str()); + } + + if (cnt < 0 ) + { + break; + } + else if (cnt == 0) + { + //DEBUG_STREAM<<"plcsrvthread::Srv_Prepare() read 0 char"<<endl; + continue; + } + else + { //reading ok + //INFO_STREAM << "plcsrvthread::run() in else cnt=" << cnt <<endl; + header_t *head; + head = reinterpret_cast<header_t *>(&buf[0]); + uint16_t btype = head->db_number; + btype = ntohs(btype); + size_t ui_size = sizeof(data_t);//TODO + INFO_STREAM << "plcsrvthread::run() before while cnt=" << cnt << " ui_size="<<ui_size <<endl; + while(cnt < ui_size && cnt >= 0) + { + if(cnt > 0) + DEBUG_STREAM << "plcsrvthread::run() after while cnt=" << cnt << " ui_size="<<ui_size <<endl; + if(cnt < ui_size) + { + try + { + Tango::DevLong count=t_PLCRack3->input_length(); + //INFO_STREAM << "plcsrvthread::run() in while count=" << count <<endl; + if(count > 0) + { + if(BUF_LEN-cnt < ui_size-cnt) + { + INFO_STREAM << "plcsrvthread::run() bytes missing=" << ui_size-cnt << " cannot fit in buffer, " << BUF_LEN-cnt << " bytes left!" <<endl; + //empty buffer and restart reading + buf = save_buf_ptr; + memset (buf,0,2*BUF_LEN); + cnt = 0; + } + //read just what's missing + if(count > ui_size-cnt) + count = ui_size-cnt; + if(count > BUF_LEN-cnt) + count = BUF_LEN-cnt; + vector<unsigned char> dtr; + t_PLCRack3->read(count, dtr); + for (unsigned int i=0; i<dtr.size(); ++i) + { + buf[cnt+i] = dtr[i]; + } + gettimeofday(&last_read, NULL); + head = reinterpret_cast<header_t *>(&buf[0]); + btype = head->db_number; + btype = ntohs(btype); + } + else + { + timespec time_to_sleep; + time_to_sleep.tv_sec=0; + //time_to_sleep.tv_nsec= 0.5 * 1000000L;//0.5ms + //time_to_sleep.tv_nsec= 10 * 1000000L;//100ms + time_to_sleep.tv_nsec= 100 * 1000000L;//100ms//TODO + nanosleep(&time_to_sleep, NULL); + } + cnt += count; + if(count > 0) + INFO_STREAM << "plcsrvthread::run() receiving for type:" << btype <<" "<< count << " more bytes, total received="<<cnt<< " expected="<<ui_size <<endl; + } + catch(Tango::DevFailed &e) + { + INFO_STREAM << __func__ << ": error reading " << e.errors[0].desc; + cnt = -1; + sleep(1); + } + } + + if(cnt < ui_size) + { + if(cnt > 0) + INFO_STREAM << "plcsrvthread::run() still missing bytes total received=" << cnt <<" < expected="<< ui_size << endl; + continue; + } + + INFO_STREAM << "plcsrvthread::run() finally received complete type:" << btype <<" length:"<< ui_size<<endl; + + }//end while(cnt < ui_size) + while(cnt > 0) + { + head = reinterpret_cast<header_t *>(&buf[0]); + btype = head->db_number; + btype = ntohs(btype); + size_t ui_size = sizeof(data_t);//TODO + DEBUG_STREAM << "plcsrvthread::run() read " << cnt << " in buffer, type:" << btype <<endl; + if(cnt >= ui_size && ui_size > 0) + { + parse_message(btype, ui_size); + cnt -= ui_size; + if(cnt > 0) + { + buf += ui_size; + INFO_STREAM << "plcsrvthread::run() after parsing " << ui_size << " there are " << cnt <<" remaining in buffer. buf moved ahead of "<< ui_size << " -> " << hex<<setw(2)<<setfill(' ')<< (int)(unsigned char) buf[0]<<","<<(int)(unsigned char) buf[1]<<","<< (int)(unsigned char) buf[2]<<","<<(int)(unsigned char) buf[3]<<","<< (int)(unsigned char) buf[4]<<","<<(int)(unsigned char) buf[5]<<","<<(int)(unsigned char) buf[6]<<","<< (int)(unsigned char) buf[7]<<endl; + } + else + { + buf = save_buf_ptr; + memset (buf,0,2*BUF_LEN); + INFO_STREAM << "plcsrvthread::run() buf empty after parsing cnt=" << cnt; + break; + } + } + else if(cnt > 0 && ui_size == 0 && btype == 0) + { + buf = save_buf_ptr; + memset (buf,0,2*BUF_LEN); + INFO_STREAM << "plcsrvthread::run() emptying buffer cnt=" << cnt << " type==0 && ui_size==0"; + cnt = 0; + break; + } + else if(cnt < ui_size) + { + INFO_STREAM << __func__ << " exiting parsing loop with " << cnt << " remaining, type=" << btype << " size="<<ui_size; + char tmp[BUF_LEN]; + memcpy(tmp,buf,cnt); + buf = save_buf_ptr; + memset (buf,0,2*BUF_LEN); + memcpy(buf,tmp,cnt); + break; + } + } + DEBUG_STREAM << "plcsrvthread::run() end of loop while (cnt > 0)"<<endl; + + } // end of message-print else + // end of do loop statement + }while ((cnt >= 0)&&(!t_PLCRack3->abortflag)); // do loop condition + }//end of accept else + } // end of while (1) +// close(t_PLCRack3->sock); + server_started=0; + return; + +} + + +void plcsrvthread::parse_message(uint16_t type, uint16_t size) +{ + INFO_STREAM << __func__ << ": entering parsing, type="<<type<< " size=" <<size << endl; + for(int k=0;k<size;) + { + stringstream tmp; + int g; + tmp << "DB"<<type<<": "<<setw(3)<<setfill(' ')<<k<<" -> "; + for(g=0; g<10; g++) + { + if(k+g>=size) + break; + tmp << " " <<hex<<setw(2)<<setfill(' ')<< (int)(unsigned char)buf[k+g]; + } + k+=g; + if(k<size) + { + tmp << " | "<<dec<<setw(3)<<setfill(' ')<<k<<hex<<" -> "; + for(g=0; g<10; g++) + { + if(k+g>=size) + break; + tmp << " " <<hex<<setw(2)<<setfill(' ')<< (int)(unsigned char)buf[k+g]; + } + k+=g; + } + DEBUG_STREAM<<tmp.str()<<dec<<endl; + } + switch(type) + { + case 500: + case 0: + case 200: + case 201: + case 202: + case 210: + case 211: + case 212: + INFO_STREAM << __func__ << ": received DB500 size=" <<size << endl; + memcpy(&t_PLCRack3->db500, buf, size); + break; + default: + INFO_STREAM << __func__ << ": message NOT recognized, type "<<type<< " size=" <<size << endl; + break; + } +} + +uint16_t plcsrvthread::plc_swap(uint16_t in) +{ + return ((in>>8)|((in&0x00ff)<<8)); +} + + + +uint32_t plcsrvthread::plc_swaplong(uint32_t in) +{ + return ((in>>16)|((in&0x0000ffff)<<16)); +} + +float plcsrvthread::htonf(float val_f) +{ + float *ret_val; + uint32_t *val_l; + uint32_t ret_val_l; + + val_l = (uint32_t *)&val_f; +#if 1 + ret_val_l = htonl(*val_l); +#else +# if __BYTE_ORDER == __LITTLE_ENDIAN + ret_val_l = __bswap_32(*val_l); +#else + ret_val_l = *val_l; +#endif +#endif + ret_val=(float *)&ret_val_l; + + return *ret_val; +} + +float plcsrvthread::ntohf(float val_f) +{ + float *ret_val; + uint32_t *val_l; + uint32_t ret_val_l; + + val_l = (uint32_t *)&val_f; +#if 1 + ret_val_l = ntohl(*val_l); +#else +# if __BYTE_ORDER == __LITTLE_ENDIAN + ret_val_l = __bswap_32(*val_l); +#else + ret_val_l = *val_l; +#endif +#endif + ret_val=(float *)&ret_val_l; + + return *ret_val; +} + +}//namespace + + diff --git a/src/plcsrvthread.h b/src/plcsrvthread.h new file mode 100644 index 0000000..8f36b9f --- /dev/null +++ b/src/plcsrvthread.h @@ -0,0 +1,92 @@ +/* + * plcsrvthread.h + * + */ + +#ifndef PLCSRVTHREAD_H +#define PLCSRVTHREAD_H + +#include <omnithread.h> +#include <tango.h> +#include <stdio.h> +#include <errno.h> + +#include <PLCRack3.h> + + +//size of the message buffer +#define BUF_LEN 200000 + +namespace PLCRack3_ns{ + +class plcsrvthread : public omni_thread, public Tango::LogAdapter{ + + private: + PLCRack3 *t_PLCRack3; + bool db20_received; + bool db24_received; + + public: + + plcsrvthread(PLCRack3 *s):Tango::LogAdapter(s){ + t_PLCRack3 = s; + + first_mesg = true; + db20_received = false; + db24_received = false; + }; + + ~plcsrvthread() { + }; +// void *StartUndetached(){ +// start_undetached(); +// } +// void *run_undetached(void *); + + protected: + void run(void *); + + int errcount; + struct timeval last_read; + char frame2[BUF_LEN]; + u_short olddata; + // tstamp_t time_before; + // intlck_db53 lastmsg; + + Tango::DeviceProxy *mydevice; + Tango::DeviceAttribute arl; + + // logalarm_t local_mesg; + + int cnt, cnt2, server_started; + bool first_mesg; + + // struct sembuf operations[1]; + int retval; + int id; + + //char buf[BUF_LEN]; + char *buf; + unsigned long push_counter; + bool allow_push; + + void Srv_Prepare(void); + uint16_t plc_swap(uint16_t in); + uint32_t plc_swaplong(uint32_t in); + void parse_message(uint16_t type, uint16_t size); + +// long ll, mm; + u_short v; + int brk; + + int idx; + + float ntohf(float val_f); + float htonf(float val_f); +}; /* end class plcsrvthread() */ + +}// namespace + +#endif + +/* EOF */ -- GitLab