From ac9ff844e77b1c17775c093602f90c2672d69300 Mon Sep 17 00:00:00 2001
From: Claudio Scafuri <claudio.scafuri@elettra.eu>
Date: Mon, 11 May 2020 13:45:54 +0200
Subject: [PATCH] first import from repo fermi/server/pdumapper CVS release_04

---
 .gitignore                    |  19 +
 LICENSE                       | 165 ++++++
 Makefile                      |   3 +
 README.md                     |  30 +-
 src/ClassFactory.cpp          |  55 ++
 src/PduMap.cpp                | 433 ++++++++++++++++
 src/PduMap.h                  | 184 +++++++
 src/PduMapper.cpp             | 919 ++++++++++++++++++++++++++++++++++
 src/PduMapper.h               | 247 +++++++++
 src/PduMapper.xmi             |  83 +++
 src/PduMapperClass.cpp        | 699 ++++++++++++++++++++++++++
 src/PduMapperClass.h          | 206 ++++++++
 src/PduMapperStateMachine.cpp | 142 ++++++
 src/main.cpp                  |  86 ++++
 14 files changed, 3269 insertions(+), 2 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 LICENSE
 create mode 100644 Makefile
 create mode 100644 src/ClassFactory.cpp
 create mode 100644 src/PduMap.cpp
 create mode 100644 src/PduMap.h
 create mode 100644 src/PduMapper.cpp
 create mode 100644 src/PduMapper.h
 create mode 100644 src/PduMapper.xmi
 create mode 100644 src/PduMapperClass.cpp
 create mode 100644 src/PduMapperClass.h
 create mode 100644 src/PduMapperStateMachine.cpp
 create mode 100644 src/main.cpp

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f768f79
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,19 @@
+.pydevproject
+.project
+.cproject
+.settings
+obj
+bin
+core*
+*~
+*.pyc
+*.so
+*.so*
+.pylintrc
+.metadata
+.idea
+.cvsignore
+.nse_depinfo
+software
+oldsrc
+CVS
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d84c585
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,3 @@
+NAME_SRV = pdumapper-srv
+
+include ../makefiles/Make-9.3.3.in
diff --git a/README.md b/README.md
index 708bcee..5f795b3 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,29 @@
-# pdumapper
+# Project Name
+
+pdumapper
+
+## Description
+
+tango device server for mapping and and and querying Fermi and Elettra pdu devices
+
+## Installation
+
+See your institue guidelines for deploying and configuring a Tango device server.
+
+## History
+
+2020-05-10 : project created on gitlab, derived from repo fermi/server/pdumapper CVS release_04
+
+original development by Alessandro Olivo
+
+## Credits
+
+Elettra-Sincrotrone Trieste S.C.p.A. di interesse nazionale
+Strada Statale 14 - km 163,5 in AREA Science Park
+34149 Basovizza, Trieste ITALY
+
+## License
+
+GPL 3
+
 
-tango device serever for mapping and and and quering Fermi and Elettra pdu devices
\ No newline at end of file
diff --git a/src/ClassFactory.cpp b/src/ClassFactory.cpp
new file mode 100644
index 0000000..294691f
--- /dev/null
+++ b/src/ClassFactory.cpp
@@ -0,0 +1,55 @@
+/*----- PROTECTED REGION ID(PduMapper::ClassFactory.cpp) ENABLED START -----*/
+//=============================================================================
+//
+// 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 :     
+//
+// 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/>.
+// 
+// $Author: alessandro.olivo $
+//
+// $Revision: 1.1.1.1 $
+// $Date: 2017-10-02 14:01:30 $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+#include <tango.h>
+#include <PduMapperClass.h>
+
+//	Add class header files if needed
+
+
+/**
+ *	Create PduMapper Class singleton and store it in DServer object.
+ */
+
+void Tango::DServer::class_factory()
+{
+	//	Add method class init if needed
+	add_class(PduMapper_ns::PduMapperClass::init("PduMapper"));
+}
+/*----- PROTECTED REGION END -----*/	//	PduMapper::ClassFactory.cpp
diff --git a/src/PduMap.cpp b/src/PduMap.cpp
new file mode 100644
index 0000000..fa1c30c
--- /dev/null
+++ b/src/PduMap.cpp
@@ -0,0 +1,433 @@
+#include "PduMap.h"
+
+
+//PduData class methods
+
+PduData::PduData(size_t outlets_num, string pdu_name, Tango::DeviceProxy *pdu_proxy)
+{
+	outlets_count = outlets_num; 
+	name = pdu_name;
+	proxy = pdu_proxy;
+	errors = NULL;
+}
+
+void PduData::setOutletsCount(size_t count)
+{
+	outlets_count = count;
+}
+
+size_t PduData::getOutletsCount()
+{
+	return outlets_count;
+}
+
+string PduData::getDevName()
+{
+	return name;
+}
+
+void PduData::setDevName(string pdu_name)
+{
+	name = pdu_name;
+}
+
+Tango::DeviceProxy* PduData::getProxy()
+{
+	return proxy;
+}
+
+void PduData::setProxy(Tango::DeviceProxy *devPrx)
+{
+	proxy = devPrx;
+}
+
+void PduData::setErrors(Tango::DevFailed *errs)
+{
+	if(errors)	
+		delete errors;
+	errors = errs;
+}
+Tango::DevFailed* PduData::getErrors()
+{
+	return errors;
+}
+
+//ATTRIBUTE NAME
+// --> Value
+string PduData::getLabelByPos(int pos)
+{
+	validateOutletIdx(pos);
+	return label_ls[pos].value;
+}
+
+string PduData::getLabelByAttr(string attr)
+{
+	validateLabelAttr(attr);
+	int pos = atoi(attr.substr(4, 2).c_str()) - 1;
+	return getLabelByPos(pos);
+}
+
+void PduData::setLabelByPos(int pos, string value)
+{
+	validateOutletIdx(pos);
+	label_ls[pos].value = value;
+}
+
+void PduData::setLabelByAttr(string attr, string value)
+{
+	validateLabelAttr(attr);
+	int pos = atoi(attr.substr(4, 2).c_str()) - 1;
+	setLabelByPos(pos, value);
+}
+
+// --> Event
+void PduData::setLabelEventId(int pos, int id)
+{
+	validateOutletIdx(pos);
+	label_ls[pos].event = id;
+}
+void PduData::setLabelEventId(string attr, int id)
+{
+	validateLabelAttr(attr);
+	int pos = atoi(attr.substr(4, 2).c_str()) - 1;
+	setLabelEventId(pos, id);
+}
+
+//ATTRIBURTE STATE
+// --> Value
+string PduData::getStateByPos(int pos)
+{
+	validateOutletIdx(pos);
+	return state_ls[pos].value;
+}
+
+/**
+string PduData::getStateByAttr(string attr)
+{
+	validateStateAttr(attr);
+	int pos = atoi(attr.substr(5, 2).c_str()) - 1;
+	return getStateByPos(pos);
+}
+*/
+
+void PduData::setStateByPos(int pos, string value)
+{
+	validateOutletIdx(pos);
+	state_ls[pos].value = value;
+}
+
+void PduData::setStateByAttr(string attr, string value)
+{
+	validateStateAttr(attr);
+	int pos = atoi(attr.substr(5, 2).c_str()) - 1;
+	setStateByPos(pos, value);
+}	
+// --> Event
+void PduData::setStateEventId(int pos, int id)
+{
+	validateOutletIdx(pos);
+	state_ls[pos].event = id;
+}
+
+void PduData::setStateEventId(string attr, int id)
+{
+	validateStateAttr(attr);
+	int pos = atoi(attr.substr(5, 2).c_str()) - 1;
+	setStateEventId(pos, id);
+}
+
+vector<int> PduData::getAllEvents()
+{
+	vector<int> events;
+	size_t len = getOutletsCount();
+	for(unsigned int i = 0; i < len; i++ )
+	{
+		events.push_back(state_ls[i].event);
+		events.push_back(label_ls[i].event);
+	}
+	return events;
+}
+
+bool PduData::matchLabelPattern(string label)
+{
+	regex label_pattern(label, regex_constants::icase);
+	for(unsigned int i = 0; i < outlets_count; i++)
+		if (regex_match(label_ls[i].value, label_pattern))
+			return true;
+	return false;
+}
+
+void PduData::addIfMatchLabelPattern(vector<string> &outlets_ls, string label)
+{
+	regex label_pattern(label, regex_constants::icase);
+	for(unsigned int i = 0; i < outlets_count; i++)
+		if (regex_match(label_ls[i].value, label_pattern))
+			outlets_ls.push_back(label_ls[i].value);
+}
+
+void PduData::validateOutletIdx(unsigned int idx)
+{
+	if (idx >= outlets_count) 
+	{
+		stringstream idx_ss;
+		string idx_s;
+		idx_ss << idx;
+		idx_ss >> idx_s;
+		throw NotValidOutletIndex(name, idx_s);
+	}
+}
+
+void PduData::validateStateAttr(string attr_name)
+{
+	/** Expected "stateXX" ('X' is a digit) in attr_name **/
+	
+	if (attr_name.size() == 7 && attr_name.substr(0, 5).compare("state") == 0) 
+		if(isdigit(attr_name[5]) && isdigit(attr_name[6]))
+			return;
+	throw NotValidAttrName(attr_name);
+}
+
+void PduData::validateLabelAttr(string attr_name)
+{
+	/** Expected "nameXX" ('X' is a digit) in attr_name **/
+	
+	if (attr_name.size() == 6 && attr_name.substr(0, 4).compare("name") == 0) 
+		if(isdigit(attr_name[4]) && isdigit(attr_name[5]))
+			return;
+	throw NotValidAttrName(attr_name);
+}
+
+// "PduMap" CLASS METHODS
+
+PduMap* PduMap::instance = NULL;
+
+PduMap::PduMap(){}
+
+void PduMap::resetInstance()
+{
+	delete instance;
+	instance = NULL;
+}
+
+PduMap* PduMap::getInstance()
+{
+	if (instance == 0)
+	{
+		instance = new PduMap();
+	}
+	return instance;
+}
+
+void PduMap::addPduData(size_t outletsNum, string pdu_name, Tango::DeviceProxy *pdu_proxy)
+{
+	if(isPduName(pdu_name))
+		throw PduNameAlreadyExists(pdu_name);
+	else
+		pduData_ls.emplace_back(outletsNum, pdu_name, pdu_proxy);
+}
+
+void PduMap::deletePduData(string pdu_name)
+{
+	unsigned int idx = getIdxPduData(pdu_name);
+	Tango::DeviceProxy *prxy = pduData_ls[idx].getProxy();
+	Tango::DevFailed *errs = pduData_ls[idx].getErrors();
+	if (prxy)
+		delete prxy;
+	if(errs)
+		delete errs;
+	pduData_ls.erase(pduData_ls.begin() + idx);
+}
+
+void PduMap::getPduInfoFromName(vector<string> &pdu_info, string pdu_name)
+{	
+	unsigned int idx = getIdxPduData(pdu_name);
+	Tango::DevFailed *errors = pduData_ls[idx].getErrors();
+	if(errors)
+		throw *errors;
+	size_t outlets_num = pduData_ls[idx].getOutletsCount();
+	for(size_t j = 0; j < outlets_num; j++)
+	{
+		pdu_info.push_back(pduData_ls[idx].getLabelByPos(j));
+		pdu_info.push_back(pduData_ls[idx].getStateByPos(j));
+	}
+}
+
+void PduMap::getPduListFromLabel(vector<string> &pdu_ls, string label)
+{
+	size_t len = pduData_ls.size();
+	for(unsigned int i = 0; i < len; i++)
+		if(!pduData_ls[i].getErrors())
+			if(pduData_ls[i].matchLabelPattern(label))
+				pdu_ls.push_back(pduData_ls[i].getDevName());
+}
+
+void PduMap::getPduListFromName(vector<string> &pdu_ls, string pdu_name)
+{
+	regex name_pattern(pdu_name, regex_constants::icase);
+	size_t len = pduData_ls.size();
+	for(unsigned int i = 0; i < len; i++)
+		if(regex_match(pduData_ls[i].getDevName(), name_pattern))
+			pdu_ls.push_back(pduData_ls[i].getDevName());
+}
+
+void PduMap::getOutletsListFromLabel(vector<string> &outlets_ls, string label)
+{
+	size_t len = pduData_ls.size();
+	for(unsigned int i = 0; i < len; i++)
+		if(!pduData_ls[i].getErrors())
+			pduData_ls[i].addIfMatchLabelPattern(outlets_ls, label);
+}
+
+void PduMap::getPduInErrorList(string &pdu_ls)
+{
+	size_t len = pduData_ls.size();
+	pdu_ls = "";
+	for(unsigned int i = 0; i < len; i++)
+		if(pduData_ls[i].getErrors())
+			pdu_ls += "- " + pduData_ls[i].getDevName() + "\n";
+}
+
+void PduMap::getAllPduEvents(vector<int> &events, string pdu_name)
+{
+	unsigned int idx = getIdxPduData(pdu_name);
+	events = pduData_ls[idx].getAllEvents();
+}
+
+void PduMap::getAllPduEvents(vector<int> &events, unsigned int pos)
+{
+	validatePduIndex(pos);
+	events = pduData_ls[pos].getAllEvents();
+}
+
+Tango::DeviceProxy* PduMap::getPduProxy(string pdu_name)
+{
+	unsigned int idx = getIdxPduData(pdu_name);
+	return pduData_ls[idx].getProxy();
+}
+
+Tango::DeviceProxy* PduMap::getPduProxy(unsigned int pos)
+{
+	validatePduIndex(pos);
+	return pduData_ls[pos].getProxy();
+}
+
+Tango::DevFailed* PduMap::getPduErrors(string pdu_name)
+{
+	unsigned int idx = getIdxPduData(pdu_name);
+	return pduData_ls[idx].getErrors();
+}
+
+Tango::DevFailed* PduMap::getPduErrors(unsigned int pos)
+{
+	validatePduIndex(pos);
+	return pduData_ls[pos].getErrors();
+}
+
+void PduMap::updateOutletState(string pdu_name, string attr_name, string new_value)
+{
+	unsigned int idx = getIdxPduData(pdu_name);
+	pduData_ls[idx].setStateByAttr(attr_name, new_value);
+}
+
+void PduMap::updateOutletLabel(string pdu_name, string attr_name, string new_value)
+{
+	unsigned int idx = getIdxPduData(pdu_name);
+	pduData_ls[idx].setLabelByAttr(attr_name, new_value);
+}
+
+void PduMap::updateAttrEventId(string pdu_name, string attr_name, int id)
+{
+	unsigned int idx = getIdxPduData(pdu_name);
+	if (attr_name.substr(0, 5).compare("state") == 0)
+	{	
+		pduData_ls[idx].setStateEventId(attr_name, id);
+		return;
+	}
+	else if (attr_name.substr(0, 4).compare("name") == 0)
+	{
+		pduData_ls[idx].setLabelEventId(attr_name, id);
+		return;
+	}
+	else
+	{
+		throw NotValidAttrName(attr_name);
+	}
+}
+
+void PduMap::updatePduError(string pdu_name, Tango::DevFailed *errs)
+{
+ 	unsigned int idx = getIdxPduData(pdu_name);
+	pduData_ls[idx].setErrors(errs);
+}
+
+string PduMap::toString()
+{
+	stringstream pdu_map_str;
+	size_t pdu_num = pduData_ls.size();
+	for(size_t i = 0; i < pdu_num; i++)
+	{
+		pdu_map_str << "PDU: " << pduData_ls[i].getDevName() << ": " << endl;
+		size_t outlest_num = pduData_ls[i].getOutletsCount();
+		for(size_t j = 0; j < outlest_num; j++)
+		{
+			pdu_map_str << "Outlet" << j + 1 << ": [ " 
+						<< pduData_ls[i].getLabelByPos(j) << " | "
+						<< pduData_ls[i].getStateByPos(j) << " ], " 
+						<< endl << flush; 
+		}
+	}
+	return pdu_map_str.str();
+}
+
+size_t PduMap::getPduNum()
+{
+	return pduData_ls.size();	
+}
+
+bool PduMap::inError()
+{
+	size_t len = pduData_ls.size();
+	for(unsigned int i = 0; i < len; i++)		
+		if(pduData_ls[i].getErrors())
+			return true;
+	return false;
+}
+
+void PduMap::getCompletePduList(vector<string> pdu_ls)
+{
+	size_t len = pduData_ls.size();
+	for(unsigned int i = 0; i < len; i++)
+		pdu_ls.push_back(pduData_ls[i].getDevName());
+}
+
+unsigned int PduMap::getIdxPduData(string pdu_name)
+{
+	size_t len = pduData_ls.size();
+	for(unsigned int i = 0 ; i < len; i++)
+		if(pdu_name.compare(pduData_ls[i].getDevName()) == 0)
+			return i;
+	throw NotValidPduName(pdu_name);
+}
+
+bool PduMap::isPduName(string pdu_name)
+{
+	size_t len = pduData_ls.size();
+	for(unsigned int i = 0 ; i < len; i++)
+		if(pdu_name.compare(pduData_ls[i].getDevName()) == 0)
+			return true;
+	return false;
+}
+
+void PduMap::validatePduIndex(unsigned int idx)
+{
+	size_t num = pduData_ls.size();
+	if (idx >= num)
+	{
+		stringstream idx_ss;
+		string idx_s;
+		idx_ss << idx;
+		idx_ss >> idx_s;
+		throw NotValidPduIndex(idx_s);
+	}
+}
+
diff --git a/src/PduMap.h b/src/PduMap.h
new file mode 100644
index 0000000..ef12848
--- /dev/null
+++ b/src/PduMap.h
@@ -0,0 +1,184 @@
+#include <string>
+#include <vector>
+#include <cctype>
+#include <regex>
+
+#include <omnithread.h>
+#include <tango.h>
+
+#define MAX_OUTLETS_COUNT 16
+
+
+struct MapException: runtime_error{
+	
+	string error_code;
+	MapException(string msg, string err_code) : runtime_error(msg), 
+												error_code(err_code) {};
+};
+
+struct NotValidPduName: MapException{
+
+	NotValidPduName(string pdu_name): MapException(
+	"PDU:\" " + pdu_name + " \" doesn't exist in the pdu map.", "PDU_NOT_EXISTS"){};
+};
+
+struct NotValidAttrName : MapException{
+	
+	NotValidAttrName(string attr_name): MapException(
+	"Attribute name: \" " + attr_name + " \" doesn't recognized,\
+	  expected \"nameXX\" or \"stateXX\" (X is a digit)", "NOT_VALID_ATTR"){};
+};
+
+struct PduNameAlreadyExists : MapException{
+	
+	PduNameAlreadyExists(string pdu_name): MapException(
+	"PDU: \" " + pdu_name + " \" already exists in the pdu map", "PDU_ALREADY_EXISTS"){};
+};
+
+struct NotValidPduIndex : MapException{
+	
+	NotValidPduIndex(string pdu_idx): MapException(
+	"PDU map has not the pdu with index " + pdu_idx, "PDU_INDEX_NOT_VALID"){};
+};
+
+struct NotValidOutletIndex : MapException{
+	
+	NotValidOutletIndex(string pdu_name, string outlet_idx): MapException(
+	"PDU: \"" + pdu_name + "\" has not outlet " + outlet_idx + ".", "OUTLET_INDEX_NOT_VALID"){};
+};
+/** AttrData class definition **/
+class AttrData
+{
+
+public:
+	/** DATA **/
+	
+	int event;
+	string value;
+};
+
+/** PduData class definition **/
+class PduData
+{
+
+private:
+	/** DATA **/
+	
+	size_t outlets_count;
+	string name;
+	Tango::DeviceProxy *proxy;
+	Tango::DevFailed *errors;
+	AttrData state_ls[MAX_OUTLETS_COUNT];
+	AttrData label_ls[MAX_OUTLETS_COUNT];
+	
+	/** FUNCTIONS **/
+	
+	//Validation
+	void validateOutletIdx(unsigned int i);
+	void validateLabelAttr(string attr_name);
+	void validateStateAttr(string attr_name);
+	
+public:
+	/** FUNCTIONS **/
+	
+	PduData(size_t outletsNum, string dev_name, Tango::DeviceProxy *pdu_proxy);
+	
+	void setOutletsCount(size_t count);
+	size_t getOutletsCount();
+	
+	string getDevName();
+	void setDevName(string pdu_name);
+	
+	Tango::DeviceProxy* getProxy();
+	void setProxy(Tango::DeviceProxy *devPrx);
+	
+	void setErrors(Tango::DevFailed *errs);
+	Tango::DevFailed *getErrors();
+	
+	// Attribute Name
+	string getLabelByPos(int pos);
+	string getLabelByAttr(string attr);
+	void setLabelByPos(int pos, string value);
+	void setLabelByAttr(string attr, string value);
+	
+	void setLabelEventId(int pos, int id);
+	void setLabelEventId(string attr, int id);
+		
+	// Attribute State
+	string getStateByPos(int pos);
+	string getStateByAttr(string attr);
+	void setStateByPos(int pos, string value);
+	void setStateByAttr(string attr, string value);
+	
+	void setStateEventId(int pos, int id);
+	void setStateEventId(string attr, int id);
+	
+	vector<int> getAllEvents();
+	
+	bool matchLabelPattern(string label);
+	void addIfMatchLabelPattern(vector<string> &outlets_ls, string label);
+	
+};
+
+
+/** PduMap class definition **/
+class PduMap
+{
+
+private:
+	/** DATA **/
+	
+	static PduMap *instance;
+	vector<PduData> pduData_ls;
+	
+	/** FUNCTIONS **/
+	
+	PduMap();
+	
+	//Validation
+	unsigned int getIdxPduData(string pdu_name);
+	bool isPduName(string pdu_name);
+	void validatePduIndex(unsigned int idx);
+	
+public:
+	/** DATA **/
+	
+	omni_mutex mutex;
+	
+	/** FUNCTIONS **/
+	
+	static void resetInstance();
+	static PduMap *getInstance();
+	
+	//Insert and delete PduData
+	void addPduData(size_t outletsNum, string dev_name, Tango::DeviceProxy *pdu_proxy);
+	void deletePduData(string dev_name);
+	
+	//Update data PduData
+	void updateOutletLabel(string pdu_name, string attr_name, string new_value);
+	void updateOutletState(string pdu_name, string attr_name, string new_value);
+	void updateAttrEventId(string pdu_name, string attr_name, int id);
+	void updatePduError(string pdu_name, Tango::DevFailed *errs);
+	
+	//Extract data PduData
+	void getCompletePduList(vector<string> pdu_ls);
+	void getPduInfoFromName(vector<string> &pdu_info, string pdu_name);
+	void getPduListFromLabel(vector<string> &pdu_ls, string label);
+	void getPduListFromName(vector<string> &pdu_ls, string pdu_name);
+	void getOutletsListFromLabel(vector<string> &outlets_ls, string label_pattern);
+	void getPduInErrorList(string &pdu_ls);
+	
+	void getAllPduEvents(vector<int> &events, string pdu_name);
+	void getAllPduEvents(vector<int> &events, unsigned int pos);
+	Tango::DeviceProxy* getPduProxy(string pdu_name);
+	Tango::DeviceProxy* getPduProxy(unsigned int pos);
+	Tango::DevFailed* getPduErrors(string pdu_name);
+	Tango::DevFailed* getPduErrors(unsigned int pos);
+	
+	//Helper
+	string toString();
+	size_t getPduNum();
+	bool inError();
+
+};
+
diff --git a/src/PduMapper.cpp b/src/PduMapper.cpp
new file mode 100644
index 0000000..8ece63f
--- /dev/null
+++ b/src/PduMapper.cpp
@@ -0,0 +1,919 @@
+/*----- PROTECTED REGION ID(PduMapper.cpp) ENABLED START -----*/
+//=============================================================================
+//
+// file :        PduMapper.cpp
+//
+// description : C++ source for the PduMapper 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
+//               PduMapper are implemented in this file.
+//
+// project :     
+//
+// 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/>.
+// 
+// $Author: alessandro.olivo $
+//
+// $Revision: 1.4 $
+// $Date: 2017-11-02 09:40:30 $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#include <PduMapper.h>
+#include <PduMapperClass.h>
+#include <algorithm>
+#include <iomanip>
+
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper.cpp
+
+/**
+ *  PduMapper class description:
+ *    
+ */
+
+//================================================================
+//  The following table gives the correspondence
+//  between command and method names.
+//
+//  Command name                     |  Method name
+//================================================================
+//  State                            |  dev_state
+//  Status                           |  dev_status
+//  GetPduListFromNamePattern        |  get_pdu_list_from_name_pattern
+//  GetPduListFromOutletPattern      |  get_pdu_list_from_outlet_pattern
+//  GetPduInfoFromName               |  get_pdu_info_from_name
+//  GetOutletsListFromOutletPattern  |  get_outlets_list_from_outlet_pattern
+//================================================================
+
+//================================================================
+//  Attributes managed is:
+//================================================================
+//================================================================
+
+namespace PduMapper_ns
+{
+/*----- PROTECTED REGION ID(PduMapper::namespace_starting) ENABLED START -----*/
+
+//	static initializations
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::namespace_starting
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::PduMapper()
+ *	Description : Constructors for a Tango device
+ *                implementing the classPduMapper
+ */
+//--------------------------------------------------------
+PduMapper::PduMapper(Tango::DeviceClass *cl, string &s)
+ : TANGO_BASE_CLASS(cl, s.c_str())
+{
+	/*----- PROTECTED REGION ID(PduMapper::constructor_1) ENABLED START -----*/
+	init_device();
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::constructor_1
+}
+//--------------------------------------------------------
+PduMapper::PduMapper(Tango::DeviceClass *cl, const char *s)
+ : TANGO_BASE_CLASS(cl, s)
+{
+	/*----- PROTECTED REGION ID(PduMapper::constructor_2) ENABLED START -----*/
+	init_device();
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::constructor_2
+}
+//--------------------------------------------------------
+PduMapper::PduMapper(Tango::DeviceClass *cl, const char *s, const char *d)
+ : TANGO_BASE_CLASS(cl, s, d)
+{
+	/*----- PROTECTED REGION ID(PduMapper::constructor_3) ENABLED START -----*/
+	init_device();
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::constructor_3
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::delete_device()
+ *	Description : will be called at device destruction or at init command
+ */
+//--------------------------------------------------------
+void PduMapper::delete_device()
+{
+	DEBUG_STREAM << "PduMapper::delete_device() " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::delete_device) ENABLED START -----*/
+	
+	//	Delete device allocated objects
+	vector<int> events_id;
+	Tango::DeviceProxy *pdu_proxy;
+	Tango::DevFailed *pdu_error;
+	size_t pdu_num = pdu_map->getPduNum();
+
+	for(size_t i = 0 ; i < pdu_num; i++)
+	{
+		pdu_map->getAllPduEvents(events_id, i);
+		pdu_proxy = pdu_map->getPduProxy(i);
+		pdu_error = pdu_map->getPduErrors(i);
+		size_t events_num = events_id.size();
+		for(size_t j = 0; j < events_num; j ++)
+		{			
+			pdu_proxy->unsubscribe_event(events_id[j]);
+			DEBUG_STREAM << "Unsubscribe event: " << events_id[j] << " from " << pdu_proxy->dev_name() << endl;
+		}
+		DEBUG_STREAM << "Delete proxy end error: " << pdu_proxy->dev_name() << endl;
+		delete pdu_proxy;
+		if (pdu_error)
+			delete pdu_error;
+	}
+	
+	if (dbTangoProxy)
+		delete dbTangoProxy;
+	
+	if (attrChngCllBck)
+		delete attrChngCllBck;
+	
+	if (pdu_map)
+		PduMap::resetInstance();
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::delete_device
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::init_device()
+ *	Description : will be called at device initialization.
+ */
+//--------------------------------------------------------
+void PduMapper::init_device()
+{
+	DEBUG_STREAM << "PduMapper::init_device() create device " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::init_device_before) ENABLED START -----*/
+	
+	//	Initialization before get_device_property() call
+	
+	dbTangoProxy = new Tango::DeviceProxy("sys/database/2");
+	attrChngCllBck = new AttributeChangeCallBack();
+	pdu_map = PduMap::getInstance();
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::init_device_before
+	
+
+	//	Get the device properties from database
+	get_device_property();
+	
+	//	No longer if mandatory property not set. 
+	if (mandatoryNotDefined)
+		return;
+
+	/*----- PROTECTED REGION ID(PduMapper::init_device) ENABLED START -----*/
+	
+	//	Initialize device
+	vector<string> pdu_list;
+	unmapped_pdu_ls = "";
+	set_state(Tango::UNKNOWN);
+	
+	try
+	{
+		createPduList(pdu_list);
+	}
+	catch(Tango::DevFailed &e)
+	{
+			stringstream descr;
+			descr << "Device server can't create the pdu map."
+				  << "Error occurred. " << endl
+				  << "Reason: " << e.errors[0].reason << endl
+				  << "Description: " << e.errors[0].desc << endl
+				  << "Origin: " << e.errors[0].origin;
+
+			set_state(Tango::FAULT);
+			set_status(descr.str());
+			return;
+	}
+	
+	tangodb_pdu_count = pdu_list.size();
+	for(unsigned int i = 0; i < tangodb_pdu_count; i++)
+	{
+		try
+		{
+			addPduData(pdu_list[i]);
+		}
+		catch(Tango::DevFailed &e)
+		{
+			unmapped_pdu_ls += "- " + pdu_list[i] + "\n";
+			ERROR_STREAM << "PduMapper::init_device() create device "
+					<< device_name << endl << "Reason: "
+					<< e.errors[0].reason << endl
+					<< "Description: " << e.errors[0].desc << endl
+					<< "Origin: " << e.errors[0].origin;
+		}
+		catch(MapException &e)
+		{
+			ERROR_STREAM << "PduMapper::init_device() create device "
+					<< device_name << " - " << e.what();
+			unmapped_pdu_ls += "- " + pdu_list[i] + "\n";
+		}
+		
+		
+	}
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::init_device
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::get_device_property()
+ *	Description : Read database to initialize property data members.
+ */
+//--------------------------------------------------------
+void PduMapper::get_device_property()
+{
+	/*----- PROTECTED REGION ID(PduMapper::get_device_property_before) ENABLED START -----*/
+	
+	//	Initialize property data members
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::get_device_property_before
+
+	mandatoryNotDefined = false;
+
+	//	Read device properties from database.
+	Tango::DbData	dev_prop;
+	dev_prop.push_back(Tango::DbDatum("pduListPattern"));
+
+	//	is there at least one property to be read ?
+	if (dev_prop.size()>0)
+	{
+		//	Call database and extract values
+		if (Tango::Util::instance()->_UseDb==true)
+			get_db_device()->get_property(dev_prop);
+	
+		//	get instance on PduMapperClass to get class property
+		Tango::DbDatum	def_prop, cl_prop;
+		PduMapperClass	*ds_class =
+			(static_cast<PduMapperClass *>(get_device_class()));
+		int	i = -1;
+
+		//	Try to initialize pduListPattern from class property
+		cl_prop = ds_class->get_class_property(dev_prop[++i].name);
+		if (cl_prop.is_empty()==false)	cl_prop  >>  pduListPattern;
+		else {
+			//	Try to initialize pduListPattern from default device value
+			def_prop = ds_class->get_default_device_property(dev_prop[i].name);
+			if (def_prop.is_empty()==false)	def_prop  >>  pduListPattern;
+		}
+		//	And try to extract pduListPattern value from database
+		if (dev_prop[i].is_empty()==false)	dev_prop[i]  >>  pduListPattern;
+		//	Property StartDsPath is mandatory, check if has been defined in database.
+		check_mandatory_property(cl_prop, dev_prop[i]);
+
+	}
+
+	/*----- PROTECTED REGION ID(PduMapper::get_device_property_after) ENABLED START -----*/
+	
+	//	Check device property data members init
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::get_device_property_after
+}
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::check_mandatory_property()
+ *	Description : For mandatory properties check if defined in database.
+ */
+//--------------------------------------------------------
+void PduMapper::check_mandatory_property(Tango::DbDatum &class_prop, Tango::DbDatum &dev_prop)
+{
+	//	Check if all properties are empty
+	if (class_prop.is_empty() && dev_prop.is_empty())
+	{
+		TangoSys_OMemStream	tms;
+		tms << endl <<"Property \'" << dev_prop.name;
+		if (Tango::Util::instance()->_UseDb==true)
+			tms << "\' is mandatory but not defined in database";
+		else
+			tms << "\' is mandatory but cannot be defined without database";
+		string	status(get_status());
+		status += tms.str();
+		set_status(status);
+		mandatoryNotDefined = true;
+		/*----- PROTECTED REGION ID(PduMapper::check_mandatory_property) ENABLED START -----*/
+		cerr << tms.str() << " for " << device_name << endl;
+		
+		/*----- PROTECTED REGION END -----*/	//	PduMapper::check_mandatory_property
+	}
+}
+
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::always_executed_hook()
+ *	Description : method always executed before any command is executed
+ */
+//--------------------------------------------------------
+void PduMapper::always_executed_hook()
+{
+	DEBUG_STREAM << "PduMapper::always_executed_hook()  " << device_name << endl;
+	if (mandatoryNotDefined)
+	{
+		string	status(get_status());
+		Tango::Except::throw_exception(
+					(const char *)"PROPERTY_NOT_SET",
+					status.c_str(),
+					(const char *)"PduMapper::always_executed_hook()");
+	}
+	/*----- PROTECTED REGION ID(PduMapper::always_executed_hook) ENABLED START -----*/
+	
+	//	code always executed before all requests
+	
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::always_executed_hook
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::read_attr_hardware()
+ *	Description : Hardware acquisition for attributes
+ */
+//--------------------------------------------------------
+void PduMapper::read_attr_hardware(TANGO_UNUSED(vector<long> &attr_list))
+{
+	DEBUG_STREAM << "PduMapper::read_attr_hardware(vector<long> &attr_list) entering... " << endl;
+	/*----- PROTECTED REGION ID(PduMapper::read_attr_hardware) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::read_attr_hardware
+}
+
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::add_dynamic_attributes()
+ *	Description : Create the dynamic attributes if any
+ *                for specified device.
+ */
+//--------------------------------------------------------
+void PduMapper::add_dynamic_attributes()
+{
+	/*----- PROTECTED REGION ID(PduMapper::add_dynamic_attributes) ENABLED START -----*/
+	
+	//	Add your own code to create and add dynamic attributes if any
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::add_dynamic_attributes
+}
+
+//--------------------------------------------------------
+/**
+ *	Command State related method
+ *	Description: This command gets the device state (stored in its device_state data member) and returns it to the caller.
+ *
+ *	@returns Device state
+ */
+//--------------------------------------------------------
+Tango::DevState PduMapper::dev_state()
+{
+	DEBUG_STREAM << "PduMapper::State()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::dev_state) ENABLED START -----*/
+	
+	//	Add your own code
+	Tango::DevState	argout = get_state();	
+	
+	if (argout != Tango::FAULT)
+	{
+		pdu_map->mutex.lock();
+		try
+		{
+			if(!pdu_map->inError() and unmapped_pdu_ls == "")
+				argout = Tango::ON;
+			else
+				argout = Tango::UNKNOWN;
+			pdu_map->mutex.unlock();
+		}
+		catch(MapException &e)
+		{
+			pdu_map->mutex.unlock();
+			ERROR_STREAM << "PduMapper::Status() - "
+					 << device_name << " - " << e.what();
+			Tango::Except::throw_exception(
+				e.error_code,
+				e.what(),
+				"PduMapper::Status()");
+		}
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::dev_state
+	set_state(argout);    // Give the state to Tango.
+	if (argout!=Tango::ALARM)
+		DeviceImpl::dev_state();
+	return get_state();  // Return it after Tango management.
+}
+//--------------------------------------------------------
+/**
+ *	Command Status related method
+ *	Description: This command gets the device status (stored in its device_status data member) and returns it to the caller.
+ *
+ *	@returns Device status
+ */
+//--------------------------------------------------------
+Tango::ConstDevString PduMapper::dev_status()
+{
+	DEBUG_STREAM << "PduMapper::Status()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::dev_status) ENABLED START -----*/
+	
+	//	Add your own code
+	string pdu_in_err_ls;
+	string status = get_status();
+	
+	if (get_state() != Tango::FAULT)
+	{
+		stringstream status_ss;
+		size_t pdu_count;
+		pdu_map->mutex.lock();
+		try
+		{
+			pdu_map->getPduInErrorList(pdu_in_err_ls);
+			pdu_count = pdu_map->getPduNum();
+			pdu_map->mutex.unlock();
+		}
+		catch(MapException &e)
+		{
+			pdu_map->mutex.unlock();
+			ERROR_STREAM << "PduMapper::Status() - "
+					 << device_name << " - " << e.what();
+			Tango::Except::throw_exception(
+				e.error_code,
+				e.what(),
+				"PduMapper::Status()");
+		}
+		if(pdu_in_err_ls == "" and  unmapped_pdu_ls == "")
+		{
+			status_ss << pdu_count << " of " << tangodb_pdu_count 		
+					  << " PDU device server mapped and responsive" << endl;
+		}
+		else
+		{
+			status_ss << "The device server doesn't know the current "
+						 "and complete PDU device servers situation." 
+					  << endl << pdu_count << " of " << tangodb_pdu_count 
+					  << " PDU device servers mapped." << endl
+					  << ((unmapped_pdu_ls != "") ?
+					  "The following PDU device servers are NOT mapped: \n" 
+					  + unmapped_pdu_ls : "") 
+					  << ((pdu_in_err_ls != "") ?
+					  "The following PDU device servers responds with errors: \n" 
+					  + pdu_in_err_ls : "");
+		}
+		status = status_ss.str();
+	}
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::dev_status
+	set_status(status);               // Give the status to Tango.
+	return DeviceImpl::dev_status();  // Return it.
+}
+//--------------------------------------------------------
+/**
+ *	Command GetPduListFromNamePattern related method
+ *	Description: 
+ *
+ *	@param argin Regex pattern, that indentify part of the Tango name of a pdu (es. uh/pdu/.* )
+ *	@returns List of Tango pdu names matched (could return one or zero pdu name)
+ */
+//--------------------------------------------------------
+Tango::DevVarStringArray *PduMapper::get_pdu_list_from_name_pattern(Tango::DevString argin)
+{
+	Tango::DevVarStringArray *argout;
+	DEBUG_STREAM << "PduMapper::GetPduListFromNamePattern()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::get_pdu_list_from_name_pattern) ENABLED START -----*/
+	
+	//	Add your own code
+	stringstream ssname;
+	string name_pattern;
+        
+	ssname << argin << flush;
+	name_pattern = ssname.str();
+        
+	vector<string> pdu_ls;
+	argout = new Tango::DevVarStringArray();
+	
+	pdu_map->mutex.lock();
+	try
+	{
+		pdu_map->getPduListFromName(pdu_ls, name_pattern);
+		pdu_map->mutex.unlock();
+	}
+	catch(MapException &e)
+	{
+		pdu_map->mutex.unlock();
+		ERROR_STREAM << "PduMapper::get_pdu_list_from_name_pattern() - "
+					 << device_name << " - " << e.what();
+		
+		delete argout;
+		Tango::Except::throw_exception(
+		e.error_code,
+		e.what(),
+		"PduMapper::get_pdu_list_from_name()");
+	}
+	catch(regex_error &e)
+	{
+		pdu_map->mutex.unlock();
+		ERROR_STREAM << "PduMapper::get_pdu_list_from_name_pattern() - "
+					 << device_name << " - " << e.what();
+		
+		delete argout;
+		Tango::Except::throw_exception(
+		"PduMapper::get_pdu_list_from_name_pattern()",
+                "Malformed regular expression",
+                e.what() + string(" code: ") + to_string(e.code()));
+	}
+	
+	size_t len = pdu_ls.size();
+	argout->length(len);
+	
+	for(unsigned int i = 0; i < len; i++)
+		(*argout)[i] = CORBA::string_dup(pdu_ls[i].c_str());
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::get_pdu_list_from_name_pattern
+	return argout;
+}
+//--------------------------------------------------------
+/**
+ *	Command GetPduListFromOutletPattern related method
+ *	Description: 
+ *
+ *	@param argin Regex pattern, that is part of an outlet name (es. .*MSCR.* )
+ *	@returns Tango name list of the pdu whose outlets match the passed argument (could return one or zero pdu name)
+ */
+//--------------------------------------------------------
+Tango::DevVarStringArray *PduMapper::get_pdu_list_from_outlet_pattern(Tango::DevString argin)
+{
+	Tango::DevVarStringArray *argout;
+	DEBUG_STREAM << "PduMapper::GetPduListFromOutletPattern()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::get_pdu_list_from_outlet_pattern) ENABLED START -----*/
+	
+	//	Add your own code
+	stringstream sslabel;
+	string label_pattern;
+        
+        sslabel << argin << flush;
+	label_pattern = sslabel.str();
+        
+	vector<string> pdu_ls;
+	argout = new Tango::DevVarStringArray();
+	
+	pdu_map->mutex.lock();
+	try
+	{
+		pdu_map->getPduListFromLabel(pdu_ls, label_pattern);	
+		pdu_map->mutex.unlock();
+	}
+	catch(MapException &e)
+	{
+		pdu_map->mutex.unlock();
+		ERROR_STREAM << "PduMapper::get_pdu_list_from_outlet_pattern() - "
+					 << device_name << " - " << e.what();
+		
+		delete argout;
+		Tango::Except::throw_exception(
+		e.error_code,
+		e.what(),
+		"PduMapper::get_pdu_list_from_outlet_pattern()");
+	}
+	catch(regex_error &e)
+	{
+		pdu_map->mutex.unlock();
+		ERROR_STREAM << "PduMapper::get_pdu_list_from_outlet_pattern() - "
+					 << device_name << " - " << e.what();
+		
+		delete argout;
+		Tango::Except::throw_exception(
+		"PduMapper::get_pdu_list_from_outlet_pattern()",
+                "Malformed regular expression",
+                e.what() + string(" code: ") + to_string(e.code()));
+	}
+	
+	size_t len = pdu_ls.size();
+	argout->length(len);
+	
+	for(unsigned int i = 0; i < len; i++)
+		(*argout)[i] = CORBA::string_dup(pdu_ls[i].c_str());
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::get_pdu_list_from_outlet_pattern
+	return argout;
+}
+//--------------------------------------------------------
+/**
+ *	Command GetPduInfoFromName related method
+ *	Description: 
+ *
+ *	@param argin PDU Tango name : ``domain/family/member``
+ *	@returns List formatted with Name and State value of the pdu like that:
+ *           [``Name01``,``State01``,``Name02``,``State02``,...]
+ */
+//--------------------------------------------------------
+Tango::DevVarStringArray *PduMapper::get_pdu_info_from_name(Tango::DevString argin)
+{
+	Tango::DevVarStringArray *argout;
+	DEBUG_STREAM << "PduMapper::GetPduInfoFromName()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::get_pdu_info_from_name) ENABLED START -----*/
+	
+	//	Add your own code
+	stringstream ssname;
+	string name;
+        
+	ssname << argin << flush; 
+	name = ssname.str();
+        
+	vector<string> pdu_info;
+	argout = new Tango::DevVarStringArray();
+	
+	pdu_map->mutex.lock();
+	try
+	{
+		pdu_map->getPduInfoFromName(pdu_info, name);
+		pdu_map->mutex.unlock();
+	}
+	catch(Tango::DevFailed &e)
+	{
+		pdu_map->mutex.unlock();
+		delete argout;
+		throw e;
+	}
+	catch(MapException &e)
+	{
+		pdu_map->mutex.unlock();
+		ERROR_STREAM << "PduMapper::get_pdu_info_from_name() - "
+					 << device_name << " - " << e.what();
+		
+		delete argout;
+		Tango::Except::throw_exception(
+		e.error_code,
+		e.what(),
+		"PduMapper::get_pdu_info_from_name()");
+	}
+	
+	size_t len = pdu_info.size();
+	argout->length(len);
+	
+	for(unsigned int i = 0; i < len; i++)
+		(*argout)[i] = CORBA::string_dup(pdu_info[i].c_str());
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::get_pdu_info_from_name
+	return argout;
+}
+//--------------------------------------------------------
+/**
+ *	Command GetOutletsListFromOutletPattern related method
+ *	Description: 
+ *
+ *	@param argin Regex pattern, that is part of an outlet name (es. .*MSCR.* )
+ *	@returns List of all outlets names matched
+ */
+//--------------------------------------------------------
+Tango::DevVarStringArray *PduMapper::get_outlets_list_from_outlet_pattern(Tango::DevString argin)
+{
+	Tango::DevVarStringArray *argout;
+	DEBUG_STREAM << "PduMapper::GetOutletsListFromOutletPattern()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(PduMapper::get_outlets_list_from_outlet_pattern) ENABLED START -----*/
+	
+	//	Add your own code
+	stringstream sslabel;
+	string label_pattern;
+        
+	sslabel << argin << flush; 
+	label_pattern = sslabel.str();
+        
+	vector<string> outlets_ls;
+	argout = new Tango::DevVarStringArray();
+	
+	pdu_map->mutex.lock();
+	try
+	{
+		pdu_map->getOutletsListFromLabel(outlets_ls, label_pattern);
+		pdu_map->mutex.unlock();
+	}
+	catch(MapException &e)
+	{
+		pdu_map->mutex.unlock();
+		ERROR_STREAM << "PduMapper::get_outlets_list_from_outlet_pattern() - "
+					 << device_name << " - " << e.what();
+		delete argout;
+		Tango::Except::throw_exception(
+		e.error_code,
+		e.what(),
+		"PduMapper::get_outlets_list_from_outlet_pattern()");
+	}
+	catch(regex_error &e)
+	{
+		pdu_map->mutex.unlock();
+		ERROR_STREAM << "PduMapper::get_outlets_list_from_outlet_pattern() - "
+					 << device_name << " - " << e.what();
+		delete argout;
+		Tango::Except::throw_exception(
+		"PduMapper::get_outlets_list_from_outlet_pattern()",
+                "Malformed regular expression",
+                e.what() + string(" code: ") + to_string(e.code()));
+	}
+	
+	size_t len = outlets_ls.size();
+	argout->length(len);
+	
+	for(unsigned int i = 0; i < len; i++)
+		(*argout)[i] = CORBA::string_dup(outlets_ls[i].c_str());
+		
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::get_outlets_list_from_outlet_pattern
+	return argout;
+}
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::add_dynamic_commands()
+ *	Description : Create the dynamic commands if any
+ *                for specified device.
+ */
+//--------------------------------------------------------
+void PduMapper::add_dynamic_commands()
+{
+	/*----- PROTECTED REGION ID(PduMapper::add_dynamic_commands) ENABLED START -----*/
+	
+	//	Add your own code to create and add dynamic commands if any
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::add_dynamic_commands
+}
+
+/*----- PROTECTED REGION ID(PduMapper::namespace_ending) ENABLED START -----*/
+
+//	Additional Methods
+// //--------------------------------------------------------
+// /**
+//  *	Read attribute PduList related method
+//  *	Description: 
+//  *
+//  *	Data type:	Tango::DevString
+//  *	Attr type:	Spectrum max = 300
+//  */
+// //--------------------------------------------------------
+// void PduMapper::read_PduList(Tango::Attribute &attr)
+// {
+// 	DEBUG_STREAM << "PduMapper::read_PduList(Tango::Attribute &attr) entering... " << endl;
+// 	//	Set the attribute value
+// 	attr.set_value(attr_PduList_read, 300);
+// 	
+// }
+
+
+void PduMapper::createPduList(vector<string>& pdu_ls)
+{
+	DEBUG_STREAM << "PduMapper::createPduList()" << device_name << endl;
+	
+	Tango::DeviceData ddin, ddout;
+	ddin << pduListPattern;
+
+	ddout = dbTangoProxy->command_inout("DbGetDeviceWideList", ddin);
+	ddout >> pdu_ls;
+}
+
+void PduMapper::addPduData(string dev_name)
+{
+	DEBUG_STREAM << "PduMapper::addPduData( " << dev_name << " ) - " << device_name << endl;
+	
+	unsigned short outletsNum;
+	Tango::DeviceProxy *pdu_proxy = NULL;
+	Tango::DeviceAttribute daout;
+        
+	try
+	{	
+		pdu_proxy = new Tango::DeviceProxy(dev_name);		
+		daout = pdu_proxy->read_attribute("OutletCount");
+		daout >> outletsNum;
+	}
+	catch(...)
+	{
+		if(pdu_proxy)
+			delete pdu_proxy;
+		throw;
+	}
+	try
+	{
+		//ADD PduData to pdu map object
+		pdu_map->mutex.lock();
+		pdu_map->addPduData(outletsNum, dev_name, pdu_proxy);
+		pdu_map->mutex.unlock();
+		
+		//INIT outlet info of the PduData and SUBSCRIBE change events
+		int event_id;
+		for (int i = 0; i < outletsNum; i++)
+		{
+			
+			stringstream label_attr_ss, state_attr_ss;
+			string label_attr, state_attr, label, state;
+			
+			label_attr_ss << "name" << setfill('0') << setw(2) << i + 1 << flush;
+			label_attr_ss >> label_attr;
+			state_attr_ss << "state" << setfill('0') << setw(2) << i + 1 << flush;
+			state_attr_ss >> state_attr;
+			
+			event_id = pdu_proxy->subscribe_event(label_attr, Tango::CHANGE_EVENT, attrChngCllBck);
+			pdu_map->mutex.lock();
+			pdu_map->updateAttrEventId(dev_name, label_attr, event_id);
+			pdu_map->mutex.unlock();
+			
+			event_id = pdu_proxy->subscribe_event(state_attr, Tango::CHANGE_EVENT, attrChngCllBck);
+			pdu_map->mutex.lock();
+			pdu_map->updateAttrEventId(dev_name, state_attr, event_id);
+			pdu_map->mutex.unlock();
+		}
+	}
+	catch(...)
+	{
+		pdu_map->mutex.unlock();
+		pdu_map->mutex.lock();
+		pdu_map->deletePduData(dev_name);
+		pdu_map->mutex.unlock();
+		throw;
+	}
+}
+
+void AttributeChangeCallBack::push_event(Tango::EventData *ev)
+{
+	#ifndef NDEBUG
+	std::cout << "AttributeChangeCallBack::push_event()" << endl;
+	#endif
+	PduMap *pdu_map = PduMap::getInstance();
+	Tango::DevFailed *errs = NULL;
+	string pdu_name, attr_name, value;
+	try
+	{			
+		pdu_name = ev->device->dev_name();
+		
+		if (!ev->err)
+		{			
+			attr_name = ev->attr_value->get_name();
+			transform(attr_name.begin(), attr_name.end(), attr_name.begin(), ::tolower);
+			
+			if (attr_name.substr(0, 5).compare("state") == 0)
+			{
+				Tango::DevState dev_state;
+				(*ev->attr_value) >> dev_state;
+				value = Tango::DevStateName[dev_state];
+				
+				pdu_map->mutex.lock();
+				pdu_map->updateOutletState(pdu_name, attr_name, value);
+				pdu_map->mutex.unlock();
+			}
+			else if (attr_name.substr(0, 4).compare("name") == 0)
+			{
+				(*ev->attr_value) >> value;
+				pdu_map->mutex.lock();
+				pdu_map->updateOutletLabel(pdu_name, attr_name, value);
+				pdu_map->mutex.unlock();
+			}
+			#ifndef NDEBUG
+			std::cout << "Value: " << (*ev->attr_value) << endl;
+			#endif
+		}
+		else
+			errs = new Tango::DevFailed(ev->errors);
+		
+		pdu_map->mutex.lock();
+		pdu_map->updatePduError(pdu_name, errs);
+		pdu_map->mutex.unlock();
+	}
+	catch(Tango::DevFailed &e)
+	{
+		pdu_map->mutex.unlock();
+		if (errs)
+			delete errs;
+		#ifndef NDEBUG
+		std::cout << "AttributeChangeCallBack::push_event(): could not extract data !" << endl;
+		#endif
+		Tango::Except::print_exception(*errs);
+	}
+	
+	#ifndef NDEBUG
+	pdu_map->mutex.lock();
+	std::cout << endl << pdu_map->toString() << endl;
+	pdu_map->mutex.unlock();
+	#endif
+}
+
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::namespace_ending
+} //	namespace
diff --git a/src/PduMapper.h b/src/PduMapper.h
new file mode 100644
index 0000000..3258ad2
--- /dev/null
+++ b/src/PduMapper.h
@@ -0,0 +1,247 @@
+/*----- PROTECTED REGION ID(PduMapper.h) ENABLED START -----*/
+//=============================================================================
+//
+// file :        PduMapper.h
+//
+// description : Include file for the PduMapper class
+//
+// project :     
+//
+// 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/>.
+// 
+// $Author: alessandro.olivo $
+//
+// $Revision: 1.1.1.1 $
+// $Date: 2017-10-02 14:01:30 $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#ifndef PduMapper_H
+#define PduMapper_H
+
+#include <tango.h>
+#include "PduMap.h"
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper.h
+
+/**
+ *  PduMapper class description:
+ *    
+ */
+
+namespace PduMapper_ns
+{
+/*----- PROTECTED REGION ID(PduMapper::Additional Class Declarations) ENABLED START -----*/
+
+//	Additional Class Declarations
+
+class AttributeChangeCallBack;
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::Additional Class Declarations
+
+class PduMapper : public TANGO_BASE_CLASS
+{
+
+/*----- PROTECTED REGION ID(PduMapper::Data Members) ENABLED START -----*/
+
+//	Add your own data members
+public:
+
+	Tango::DeviceProxy *dbTangoProxy;
+	AttributeChangeCallBack *attrChngCllBck;
+	PduMap* pdu_map;
+	string unmapped_pdu_ls;
+	size_t tangodb_pdu_count;
+	
+/*----- PROTECTED REGION END -----*/	//	PduMapper::Data Members
+
+//	Device property data members
+public:
+	//	pduListPattern:	Pattern that allows creation of the list of pdu, e.g. ``*/pdu/*``
+	string	pduListPattern;
+
+	bool	mandatoryNotDefined;
+
+
+//	Constructors and destructors
+public:
+	/**
+	 * Constructs a newly device object.
+	 *
+	 *	@param cl	Class.
+	 *	@param s 	Device Name
+	 */
+	PduMapper(Tango::DeviceClass *cl,string &s);
+	/**
+	 * Constructs a newly device object.
+	 *
+	 *	@param cl	Class.
+	 *	@param s 	Device Name
+	 */
+	PduMapper(Tango::DeviceClass *cl,const char *s);
+	/**
+	 * Constructs a newly device object.
+	 *
+	 *	@param cl	Class.
+	 *	@param s 	Device name
+	 *	@param d	Device description.
+	 */
+	PduMapper(Tango::DeviceClass *cl,const char *s,const char *d);
+	/**
+	 * The device object destructor.
+	 */
+	~PduMapper() {delete_device();};
+
+
+//	Miscellaneous methods
+public:
+	/*
+	 *	will be called at device destruction or at init command.
+	 */
+	void delete_device();
+	/*
+	 *	Initialize the device
+	 */
+	virtual void init_device();
+	/*
+	 *	Read the device properties from database
+	 */
+	void get_device_property();
+	/*
+	 *	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      : PduMapper::read_attr_hardware()
+	 *	Description : Hardware acquisition for attributes.
+	 */
+	//--------------------------------------------------------
+	virtual void read_attr_hardware(vector<long> &attr_list);
+
+
+	//--------------------------------------------------------
+	/**
+	 *	Method      : PduMapper::add_dynamic_attributes()
+	 *	Description : Add dynamic attributes if any.
+	 */
+	//--------------------------------------------------------
+	void add_dynamic_attributes();
+
+
+
+
+//	Command related methods
+public:
+	/**
+	 *	Command State related method
+	 *	Description: This command gets the device state (stored in its device_state data member) and returns it to the caller.
+	 *
+	 *	@returns Device state
+	 */
+	virtual Tango::DevState dev_state();
+	/**
+	 *	Command Status related method
+	 *	Description: This command gets the device status (stored in its device_status data member) and returns it to the caller.
+	 *
+	 *	@returns Device status
+	 */
+	virtual Tango::ConstDevString dev_status();
+	/**
+	 *	Command GetPduListFromNamePattern related method
+	 *	Description: 
+	 *
+	 *	@param argin Regex pattern, that indentify part of the Tango name of a pdu (es. uh/pdu/.* )
+	 *	@returns List of Tango pdu names matched (could return one or zero pdu name)
+	 */
+	virtual Tango::DevVarStringArray *get_pdu_list_from_name_pattern(Tango::DevString argin);
+	virtual bool is_GetPduListFromNamePattern_allowed(const CORBA::Any &any);
+	/**
+	 *	Command GetPduListFromOutletPattern related method
+	 *	Description: 
+	 *
+	 *	@param argin Regex pattern, that is part of an outlet name (es. .*MSCR.* )
+	 *	@returns Tango name list of the pdu whose outlets match the passed argument (could return one or zero pdu name)
+	 */
+	virtual Tango::DevVarStringArray *get_pdu_list_from_outlet_pattern(Tango::DevString argin);
+	virtual bool is_GetPduListFromOutletPattern_allowed(const CORBA::Any &any);
+	/**
+	 *	Command GetPduInfoFromName related method
+	 *	Description: 
+	 *
+	 *	@param argin PDU Tango name : ``domain/family/member``
+	 *	@returns List formatted with Name and State value of the pdu like that:
+	 *           [``Name01``,``State01``,``Name02``,``State02``,...]
+	 */
+	virtual Tango::DevVarStringArray *get_pdu_info_from_name(Tango::DevString argin);
+	virtual bool is_GetPduInfoFromName_allowed(const CORBA::Any &any);
+	/**
+	 *	Command GetOutletsListFromOutletPattern related method
+	 *	Description: 
+	 *
+	 *	@param argin Regex pattern, that is part of an outlet name (es. .*MSCR.* )
+	 *	@returns List of all outlets names matched
+	 */
+	virtual Tango::DevVarStringArray *get_outlets_list_from_outlet_pattern(Tango::DevString argin);
+	virtual bool is_GetOutletsListFromOutletPattern_allowed(const CORBA::Any &any);
+
+
+	//--------------------------------------------------------
+	/**
+	 *	Method      : PduMapper::add_dynamic_commands()
+	 *	Description : Add dynamic commands if any.
+	 */
+	//--------------------------------------------------------
+	void add_dynamic_commands();
+
+/*----- PROTECTED REGION ID(PduMapper::Additional Method prototypes) ENABLED START -----*/
+
+//	Additional Method prototypes
+ void createPduList(vector<string>&);
+ void addPduData(string dev_name);
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::Additional Method prototypes
+};
+
+/*----- PROTECTED REGION ID(PduMapper::Additional Classes Definitions) ENABLED START -----*/
+
+//	Additional Classes Definitions
+
+class AttributeChangeCallBack : public Tango::CallBack
+{
+	void push_event(Tango::EventData *ev);
+};
+
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::Additional Classes Definitions
+
+}	//	End of namespace
+
+#endif   //	PduMapper_H
diff --git a/src/PduMapper.xmi b/src/PduMapper.xmi
new file mode 100644
index 0000000..27d74c0
--- /dev/null
+++ b/src/PduMapper.xmi
@@ -0,0 +1,83 @@
+<?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="PduMapper" pogoRevision="9.1">
+    <description description="" title="" sourcePath="/home/alessandro/devel/fermi/servers/pdumapper/src" language="Cpp" filestogenerate="XMI   file,Code files,Protected Regions" license="GPL" copyright="" hasMandatoryProperty="true" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false">
+      <inheritances classname="Device_Impl" sourcePath=""/>
+      <identification contact="at gmail.com - alessadro.olivo89" author="alessadro.olivo89" emailDomain="gmail.com" classFamily="SoftwareSystem" siteSpecific="" platform="All Platforms" bus="Data Socket" manufacturer="None" reference=""/>
+    </description>
+    <deviceProperties name="pduListPattern" mandatory="true" description="Pattern that allows creation of the list of pdu, e.g. ``*/pdu/*``">
+      <type xsi:type="pogoDsl:StringType"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="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" isDynamic="false">
+      <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" concreteHere="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" isDynamic="false">
+      <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" concreteHere="true"/>
+    </commands>
+    <commands name="GetPduListFromNamePattern" description="" execMethod="get_pdu_list_from_name_pattern" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="Regex pattern, that indentify part of the Tango name of a pdu (es. uh/pdu/.* )">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="List of Tango pdu names matched (could return one or zero pdu name)">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <excludedStates>FAULT</excludedStates>
+      <excludedStates>INIT</excludedStates>
+    </commands>
+    <commands name="GetPduListFromOutletPattern" description="" execMethod="get_pdu_list_from_outlet_pattern" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="Regex pattern, that is part of an outlet name (es. .*MSCR.* )">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="Tango name list of the pdu whose outlets match the passed argument (could return one or zero pdu name)">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <excludedStates>FAULT</excludedStates>
+      <excludedStates>INIT</excludedStates>
+    </commands>
+    <commands name="GetPduInfoFromName" description="" execMethod="get_pdu_info_from_name" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="PDU Tango name : ``domain/family/member``">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="List formatted with Name and State value of the pdu like that:&#xA;[``Name01``,``State01``,``Name02``,``State02``,...]">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <excludedStates>FAULT</excludedStates>
+      <excludedStates>INIT</excludedStates>
+    </commands>
+    <commands name="GetOutletsListFromOutletPattern" description="" execMethod="get_outlets_list_from_outlet_pattern" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="Regex pattern, that is part of an outlet name (es. .*MSCR.* )">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="List of all outlets names matched">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <states name="FAULT" description="None PDU device server is mapped">
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </states>
+    <states name="ON" description="All PDU device servers are mapped and are responsive">
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </states>
+    <states name="UNKNOWN" description="One (or more) PDU device server isn`t mapped">
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </states>
+    <preferences docHome="./doc_html" makefileHome="/usr/local/tango-9.2.2/share/pogo/preferences"/>
+  </classes>
+</pogoDsl:PogoSystem>
diff --git a/src/PduMapperClass.cpp b/src/PduMapperClass.cpp
new file mode 100644
index 0000000..166817c
--- /dev/null
+++ b/src/PduMapperClass.cpp
@@ -0,0 +1,699 @@
+/*----- PROTECTED REGION ID(PduMapperClass.cpp) ENABLED START -----*/
+static const char *TagName    = "1.0.0";
+static const char *CvsPath    = "$Source: src/PduMapperClass.cpp,v $";
+static const char *SvnPath    = "$HeadURL:  $";
+static const char *HttpServer = "";
+//=============================================================================
+//
+// file :        PduMapperClass.cpp
+//
+// description : C++ source for the PduMapperClass.
+//               A singleton class derived from DeviceClass.
+//               It implements the command and attribute list
+//               and all properties and methods required
+//               by the PduMapper once per process.
+//
+// project :     
+//
+// 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/>.
+// 
+// $Author: alessandro.olivo $
+//
+// $Revision: 1.1.1.1 $
+// $Date: 2017-10-02 14:01:30 $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#include <PduMapperClass.h>
+
+/*----- PROTECTED REGION END -----*/	//	PduMapperClass.cpp
+
+//-------------------------------------------------------------------
+/**
+ *	Create PduMapperClass singleton and
+ *	return it in a C function for Python usage
+ */
+//-------------------------------------------------------------------
+extern "C" {
+#ifdef _TG_WINDOWS_
+
+__declspec(dllexport)
+
+#endif
+
+	Tango::DeviceClass *_create_PduMapper_class(const char *name) {
+		return PduMapper_ns::PduMapperClass::init(name);
+	}
+}
+
+namespace PduMapper_ns
+{
+//===================================================================
+//	Initialize pointer for singleton pattern
+//===================================================================
+PduMapperClass *PduMapperClass::_instance = NULL;
+
+//--------------------------------------------------------
+/**
+ * method : 		PduMapperClass::PduMapperClass(string &s)
+ * description : 	constructor for the PduMapperClass
+ *
+ * @param s	The class name
+ */
+//--------------------------------------------------------
+PduMapperClass::PduMapperClass(string &s):Tango::DeviceClass(s)
+{
+	cout2 << "Entering PduMapperClass constructor" << endl;
+	set_default_property();
+	write_class_property();
+
+	/*----- PROTECTED REGION ID(PduMapperClass::constructor) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::constructor
+
+	cout2 << "Leaving PduMapperClass constructor" << endl;
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		PduMapperClass::~PduMapperClass()
+ * description : 	destructor for the PduMapperClass
+ */
+//--------------------------------------------------------
+PduMapperClass::~PduMapperClass()
+{
+	/*----- PROTECTED REGION ID(PduMapperClass::destructor) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::destructor
+
+	_instance = NULL;
+}
+
+
+//--------------------------------------------------------
+/**
+ * method : 		PduMapperClass::init
+ * description : 	Create the object if not already done.
+ *                  Otherwise, just return a pointer to the object
+ *
+ * @param	name	The class name
+ */
+//--------------------------------------------------------
+PduMapperClass *PduMapperClass::init(const char *name)
+{
+	if (_instance == NULL)
+	{
+		try
+		{
+			string s(name);
+			_instance = new PduMapperClass(s);
+		}
+		catch (bad_alloc &)
+		{
+			throw;
+		}
+	}
+	return _instance;
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		PduMapperClass::instance
+ * description : 	Check if object already created,
+ *                  and return a pointer to the object
+ */
+//--------------------------------------------------------
+PduMapperClass *PduMapperClass::instance()
+{
+	if (_instance == NULL)
+	{
+		cerr << "Class is not initialised !!" << endl;
+		exit(-1);
+	}
+	return _instance;
+}
+
+
+
+//===================================================================
+//	Command execution method calls
+//===================================================================
+//--------------------------------------------------------
+/**
+ * method : 		GetPduListFromNamePatternClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *GetPduListFromNamePatternClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "GetPduListFromNamePatternClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	return insert((static_cast<PduMapper *>(device))->get_pdu_list_from_name_pattern(argin));
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		GetPduListFromOutletPatternClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *GetPduListFromOutletPatternClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "GetPduListFromOutletPatternClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	return insert((static_cast<PduMapper *>(device))->get_pdu_list_from_outlet_pattern(argin));
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		GetPduInfoFromNameClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *GetPduInfoFromNameClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "GetPduInfoFromNameClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	return insert((static_cast<PduMapper *>(device))->get_pdu_info_from_name(argin));
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		GetOutletsListFromOutletPatternClass::execute()
+ * description : 	method to trigger the execution of the command.
+ *
+ * @param	device	The device on which the command must be executed
+ * @param	in_any	The command input data
+ *
+ *	returns The command output data (packed in the Any object)
+ */
+//--------------------------------------------------------
+CORBA::Any *GetOutletsListFromOutletPatternClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "GetOutletsListFromOutletPatternClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	return insert((static_cast<PduMapper *>(device))->get_outlets_list_from_outlet_pattern(argin));
+}
+
+
+//===================================================================
+//	Properties management
+//===================================================================
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapperClass::get_class_property()
+ *	Description : Get the class property for specified name.
+ */
+//--------------------------------------------------------
+Tango::DbDatum PduMapperClass::get_class_property(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      : PduMapperClass::get_default_device_property()
+ *	Description : Return the default value for device property.
+ */
+//--------------------------------------------------------
+Tango::DbDatum PduMapperClass::get_default_device_property(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      : PduMapperClass::get_default_class_property()
+ *	Description : Return the default value for class property.
+ */
+//--------------------------------------------------------
+Tango::DbDatum PduMapperClass::get_default_class_property(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      : PduMapperClass::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 PduMapperClass::set_default_property()
+{
+	string	prop_name;
+	string	prop_desc;
+	string	prop_def;
+	vector<string>	vect_data;
+
+	//	Set Default Class Properties
+
+	//	Set Default device Properties
+	prop_name = "pduListPattern";
+	prop_desc = "Pattern that allows creation of the list of pdu, e.g. ``*/pdu/*``";
+	prop_def  = "";
+	vect_data.clear();
+	if (prop_def.length()>0)
+	{
+		Tango::DbDatum	data(prop_name);
+		data << vect_data ;
+		dev_def_prop.push_back(data);
+		add_wiz_dev_prop(prop_name, prop_desc,  prop_def);
+	}
+	else
+		add_wiz_dev_prop(prop_name, prop_desc);
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapperClass::write_class_property()
+ *	Description : Set class description fields as property in database
+ */
+//--------------------------------------------------------
+void PduMapperClass::write_class_property()
+{
+	//	First time, check if database used
+	if (Tango::Util::_UseDb == false)
+		return;
+
+	Tango::DbData	data;
+	string	classname = get_name();
+	string	header;
+	string::size_type	start, end;
+
+	//	Put title
+	Tango::DbDatum	title("ProjectTitle");
+	string	str_title("");
+	title << str_title;
+	data.push_back(title);
+
+	//	Put Description
+	Tango::DbDatum	description("Description");
+	vector<string>	str_desc;
+	str_desc.push_back("");
+	description << str_desc;
+	data.push_back(description);
+
+	//	put cvs or svn location
+	string	filename("PduMapper");
+	filename += "Class.cpp";
+
+	// check for cvs information
+	string	src_path(CvsPath);
+	start = src_path.find("/");
+	if (start!=string::npos)
+	{
+		end   = src_path.find(filename);
+		if (end>start)
+		{
+			string	strloc = src_path.substr(start, end-start);
+			//	Check if specific repository
+			start = strloc.find("/cvsroot/");
+			if (start!=string::npos && start>0)
+			{
+				string	repository = strloc.substr(0, start);
+				if (repository.find("/segfs/")!=string::npos)
+					strloc = "ESRF:" + strloc.substr(start, strloc.length()-start);
+			}
+			Tango::DbDatum	cvs_loc("cvs_location");
+			cvs_loc << strloc;
+			data.push_back(cvs_loc);
+		}
+	}
+
+	// check for svn information
+	else
+	{
+		string	src_path(SvnPath);
+		start = src_path.find("://");
+		if (start!=string::npos)
+		{
+			end = src_path.find(filename);
+			if (end>start)
+			{
+				header = "$HeadURL: ";
+				start = header.length();
+				string	strloc = src_path.substr(start, (end-start));
+				
+				Tango::DbDatum	svn_loc("svn_location");
+				svn_loc << strloc;
+				data.push_back(svn_loc);
+			}
+		}
+	}
+
+	//	Get CVS or SVN revision tag
+	
+	// CVS tag
+	string	tagname(TagName);
+	header = "$Name: ";
+	start = header.length();
+	string	endstr(" $");
+	
+	end   = tagname.find(endstr);
+	if (end!=string::npos && end>start)
+	{
+		string	strtag = tagname.substr(start, end-start);
+		Tango::DbDatum	cvs_tag("cvs_tag");
+		cvs_tag << strtag;
+		data.push_back(cvs_tag);
+	}
+	
+	// SVN tag
+	string	svnpath(SvnPath);
+	header = "$HeadURL: ";
+	start = header.length();
+	
+	end   = svnpath.find(endstr);
+	if (end!=string::npos && end>start)
+	{
+		string	strloc = svnpath.substr(start, end-start);
+		
+		string tagstr ("/tags/");
+		start = strloc.find(tagstr);
+		if ( start!=string::npos )
+		{
+			start = start + tagstr.length();
+			end   = strloc.find(filename);
+			string	strtag = strloc.substr(start, end-start-1);
+			
+			Tango::DbDatum	svn_tag("svn_tag");
+			svn_tag << strtag;
+			data.push_back(svn_tag);
+		}
+	}
+
+	//	Get URL location
+	string	httpServ(HttpServer);
+	if (httpServ.length()>0)
+	{
+		Tango::DbDatum	db_doc_url("doc_url");
+		db_doc_url << httpServ;
+		data.push_back(db_doc_url);
+	}
+
+	//  Put inheritance
+	Tango::DbDatum	inher_datum("InheritedFrom");
+	vector<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      : PduMapperClass::device_factory()
+ *	Description : Create the device object(s)
+ *                and store them in the device list
+ */
+//--------------------------------------------------------
+void PduMapperClass::device_factory(const Tango::DevVarStringArray *devlist_ptr)
+{
+	/*----- PROTECTED REGION ID(PduMapperClass::device_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::device_factory_before
+
+	//	Create devices and add it into the device list
+	for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
+	{
+		cout4 << "Device name : " << (*devlist_ptr)[i].in() << endl;
+		device_list.push_back(new PduMapper(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
+		PduMapper *dev = static_cast<PduMapper *>(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(PduMapperClass::device_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::device_factory_after
+}
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapperClass::attribute_factory()
+ *	Description : Create the attribute object(s)
+ *                and store them in the attribute list
+ */
+//--------------------------------------------------------
+void PduMapperClass::attribute_factory(vector<Tango::Attr *> &att_list)
+{
+	/*----- PROTECTED REGION ID(PduMapperClass::attribute_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::attribute_factory_before
+
+	//	Create a list of static attributes
+	create_static_attribute_list(get_class_attr()->get_attr_list());
+	/*----- PROTECTED REGION ID(PduMapperClass::attribute_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::attribute_factory_after
+}
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapperClass::pipe_factory()
+ *	Description : Create the pipe object(s)
+ *                and store them in the pipe list
+ */
+//--------------------------------------------------------
+void PduMapperClass::pipe_factory()
+{
+	/*----- PROTECTED REGION ID(PduMapperClass::pipe_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::pipe_factory_before
+	/*----- PROTECTED REGION ID(PduMapperClass::pipe_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::pipe_factory_after
+}
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapperClass::command_factory()
+ *	Description : Create the command object(s)
+ *                and store them in the command list
+ */
+//--------------------------------------------------------
+void PduMapperClass::command_factory()
+{
+	/*----- PROTECTED REGION ID(PduMapperClass::command_factory_before) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::command_factory_before
+
+
+	//	Command GetPduListFromNamePattern
+	GetPduListFromNamePatternClass	*pGetPduListFromNamePatternCmd =
+		new GetPduListFromNamePatternClass("GetPduListFromNamePattern",
+			Tango::DEV_STRING, Tango::DEVVAR_STRINGARRAY,
+			"Regex pattern, that indentify part of the Tango name of a pdu (es. uh/pdu/.* )",
+			"List of Tango pdu names matched (could return one or zero pdu name)",
+			Tango::OPERATOR);
+	command_list.push_back(pGetPduListFromNamePatternCmd);
+
+	//	Command GetPduListFromOutletPattern
+	GetPduListFromOutletPatternClass	*pGetPduListFromOutletPatternCmd =
+		new GetPduListFromOutletPatternClass("GetPduListFromOutletPattern",
+			Tango::DEV_STRING, Tango::DEVVAR_STRINGARRAY,
+			"Regex pattern, that is part of an outlet name (es. .*MSCR.* )",
+			"Tango name list of the pdu whose outlets match the passed argument (could return one or zero pdu name)",
+			Tango::OPERATOR);
+	command_list.push_back(pGetPduListFromOutletPatternCmd);
+
+	//	Command GetPduInfoFromName
+	GetPduInfoFromNameClass	*pGetPduInfoFromNameCmd =
+		new GetPduInfoFromNameClass("GetPduInfoFromName",
+			Tango::DEV_STRING, Tango::DEVVAR_STRINGARRAY,
+			"PDU Tango name : ``domain/family/member``",
+			"List formatted with Name and State value of the pdu like that:\n[``Name01``,``State01``,``Name02``,``State02``,...]",
+			Tango::OPERATOR);
+	command_list.push_back(pGetPduInfoFromNameCmd);
+
+	//	Command GetOutletsListFromOutletPattern
+	GetOutletsListFromOutletPatternClass	*pGetOutletsListFromOutletPatternCmd =
+		new GetOutletsListFromOutletPatternClass("GetOutletsListFromOutletPattern",
+			Tango::DEV_STRING, Tango::DEVVAR_STRINGARRAY,
+			"Regex pattern, that is part of an outlet name (es. .*MSCR.* )",
+			"List of all outlets names matched",
+			Tango::OPERATOR);
+	command_list.push_back(pGetOutletsListFromOutletPatternCmd);
+
+	/*----- PROTECTED REGION ID(PduMapperClass::command_factory_after) ENABLED START -----*/
+	
+	//	Add your own code
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::command_factory_after
+}
+
+//===================================================================
+//	Dynamic attributes related methods
+//===================================================================
+
+//--------------------------------------------------------
+/**
+ * method : 		PduMapperClass::create_static_attribute_list
+ * description : 	Create the a list of static attributes
+ *
+ * @param	att_list	the ceated attribute list
+ */
+//--------------------------------------------------------
+void PduMapperClass::create_static_attribute_list(vector<Tango::Attr *> &att_list)
+{
+	for (unsigned long i=0 ; i<att_list.size() ; i++)
+	{
+		string att_name(att_list[i]->get_name());
+		transform(att_name.begin(), att_name.end(), att_name.begin(), ::tolower);
+		defaultAttList.push_back(att_name);
+	}
+
+	cout2 << defaultAttList.size() << " attributes in default list" << endl;
+
+	/*----- PROTECTED REGION ID(PduMapperClass::create_static_att_list) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::create_static_att_list
+}
+
+
+//--------------------------------------------------------
+/**
+ * method : 		PduMapperClass::erase_dynamic_attributes
+ * description : 	delete the dynamic attributes if any.
+ *
+ * @param	devlist_ptr	the device list pointer
+ * @param	list of all attributes
+ */
+//--------------------------------------------------------
+void PduMapperClass::erase_dynamic_attributes(const Tango::DevVarStringArray *devlist_ptr, 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(((string)(*devlist_ptr)[i]).c_str());
+		PduMapper *dev = static_cast<PduMapper *> (dev_impl);
+
+		vector<Tango::Attribute *> &dev_att_list = dev->get_device_attr()->get_attribute_list();
+		vector<Tango::Attribute *>::iterator ite_att;
+		for (ite_att=dev_att_list.begin() ; ite_att != dev_att_list.end() ; ++ite_att)
+		{
+			string att_name((*ite_att)->get_name_lower());
+			if ((att_name == "state") || (att_name == "status"))
+				continue;
+			vector<string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name);
+			if (ite_str == defaultAttList.end())
+			{
+				cout2 << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << 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(PduMapperClass::erase_dynamic_attributes) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::erase_dynamic_attributes
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapperClass::get_attr_by_name()
+ *	Description : returns Tango::Attr * object found by name
+ */
+//--------------------------------------------------------
+Tango::Attr *PduMapperClass::get_attr_object_by_name(vector<Tango::Attr *> &att_list, string attname)
+{
+	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(PduMapperClass::Additional Methods) ENABLED START -----*/
+
+/*----- PROTECTED REGION END -----*/	//	PduMapperClass::Additional Methods
+} //	namespace
diff --git a/src/PduMapperClass.h b/src/PduMapperClass.h
new file mode 100644
index 0000000..fc3c197
--- /dev/null
+++ b/src/PduMapperClass.h
@@ -0,0 +1,206 @@
+/*----- PROTECTED REGION ID(PduMapperClass.h) ENABLED START -----*/
+//=============================================================================
+//
+// file :        PduMapperClass.h
+//
+// description : Include for the PduMapper root class.
+//               This class is the singleton class for
+//                the PduMapper device class.
+//               It contains all properties and methods which the 
+//               PduMapper requires only once e.g. the commands.
+//
+// project :     
+//
+// 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/>.
+// 
+// $Author: alessandro.olivo $
+//
+// $Revision: 1.1.1.1 $
+// $Date: 2017-10-02 14:01:30 $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+
+#ifndef PduMapperClass_H
+#define PduMapperClass_H
+
+#include <tango.h>
+#include <PduMapper.h>
+
+
+/*----- PROTECTED REGION END -----*/	//	PduMapperClass.h
+
+
+namespace PduMapper_ns
+{
+/*----- PROTECTED REGION ID(PduMapperClass::classes for dynamic creation) ENABLED START -----*/
+
+
+/*----- PROTECTED REGION END -----*/	//	PduMapperClass::classes for dynamic creation
+
+//=========================================
+//	Define classes for commands
+//=========================================
+//	Command GetPduListFromNamePattern class definition
+class GetPduListFromNamePatternClass : public Tango::Command
+{
+public:
+	GetPduListFromNamePatternClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	GetPduListFromNamePatternClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~GetPduListFromNamePatternClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<PduMapper *>(dev))->is_GetPduListFromNamePattern_allowed(any);}
+};
+
+//	Command GetPduListFromOutletPattern class definition
+class GetPduListFromOutletPatternClass : public Tango::Command
+{
+public:
+	GetPduListFromOutletPatternClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	GetPduListFromOutletPatternClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~GetPduListFromOutletPatternClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<PduMapper *>(dev))->is_GetPduListFromOutletPattern_allowed(any);}
+};
+
+//	Command GetPduInfoFromName class definition
+class GetPduInfoFromNameClass : public Tango::Command
+{
+public:
+	GetPduInfoFromNameClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	GetPduInfoFromNameClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~GetPduInfoFromNameClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<PduMapper *>(dev))->is_GetPduInfoFromName_allowed(any);}
+};
+
+//	Command GetOutletsListFromOutletPattern class definition
+class GetOutletsListFromOutletPatternClass : public Tango::Command
+{
+public:
+	GetOutletsListFromOutletPatternClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out,
+				   const char        *in_desc,
+				   const char        *out_desc,
+				   Tango::DispLevel  level)
+	:Command(name,in,out,in_desc,out_desc, level)	{};
+
+	GetOutletsListFromOutletPatternClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~GetOutletsListFromOutletPatternClass() {};
+	
+	virtual CORBA::Any *execute (Tango::DeviceImpl *dev, const CORBA::Any &any);
+	virtual bool is_allowed (Tango::DeviceImpl *dev, const CORBA::Any &any)
+	{return (static_cast<PduMapper *>(dev))->is_GetOutletsListFromOutletPattern_allowed(any);}
+};
+
+
+/**
+ *	The PduMapperClass singleton definition
+ */
+
+#ifdef _TG_WINDOWS_
+class __declspec(dllexport)  PduMapperClass : public Tango::DeviceClass
+#else
+class PduMapperClass : public Tango::DeviceClass
+#endif
+{
+	/*----- PROTECTED REGION ID(PduMapperClass::Additionnal DServer data members) ENABLED START -----*/
+	
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapperClass::Additionnal 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 PduMapperClass *init(const char *);
+		static PduMapperClass *instance();
+		~PduMapperClass();
+		Tango::DbDatum	get_class_property(string &);
+		Tango::DbDatum	get_default_device_property(string &);
+		Tango::DbDatum	get_default_class_property(string &);
+	
+	protected:
+		PduMapperClass(string &);
+		static PduMapperClass *_instance;
+		void command_factory();
+		void attribute_factory(vector<Tango::Attr *> &);
+		void pipe_factory();
+		void write_class_property();
+		void set_default_property();
+		void get_class_property();
+		string get_cvstag();
+		string get_cvsroot();
+	
+	private:
+		void device_factory(const Tango::DevVarStringArray *);
+		void create_static_attribute_list(vector<Tango::Attr *> &);
+		void erase_dynamic_attributes(const Tango::DevVarStringArray *,vector<Tango::Attr *> &);
+		vector<string>	defaultAttList;
+		Tango::Attr *get_attr_object_by_name(vector<Tango::Attr *> &att_list, string attname);
+};
+
+}	//	End of namespace
+
+#endif   //	PduMapper_H
diff --git a/src/PduMapperStateMachine.cpp b/src/PduMapperStateMachine.cpp
new file mode 100644
index 0000000..ae91618
--- /dev/null
+++ b/src/PduMapperStateMachine.cpp
@@ -0,0 +1,142 @@
+/*----- PROTECTED REGION ID(PduMapperStateMachine.cpp) ENABLED START -----*/
+//=============================================================================
+//
+// file :        PduMapperStateMachine.cpp
+//
+// description : State machine file for the PduMapper class
+//
+// project :     
+//
+// 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/>.
+// 
+// $Author: alessandro.olivo $
+//
+// $Revision: 1.1.1.1 $
+// $Date: 2017-10-02 14:01:30 $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                This file is generated by POGO
+//        (Program Obviously used to Generate tango Object)
+//=============================================================================
+
+#include <PduMapper.h>
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::PduMapperStateMachine.cpp
+
+//================================================================
+//  States   |  Description
+//================================================================
+//  FAULT    |  None PDU device server is mapped
+//  ON       |  All PDU device servers are mapped and are responsive
+//  UNKNOWN  |  One (or more) PDU device server isn`t mapped
+
+
+namespace PduMapper_ns
+{
+//=================================================
+//		Attributes Allowed Methods
+//=================================================
+
+
+//=================================================
+//		Commands Allowed Methods
+//=================================================
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::is_GetPduListFromNamePattern_allowed()
+ *	Description : Execution allowed for GetPduListFromNamePattern attribute
+ */
+//--------------------------------------------------------
+bool PduMapper::is_GetPduListFromNamePattern_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Compare device state with not allowed states.
+	if (get_state()==Tango::FAULT ||
+		get_state()==Tango::INIT)
+	{
+	/*----- PROTECTED REGION ID(PduMapper::GetPduListFromNamePatternStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::GetPduListFromNamePatternStateAllowed
+		return false;
+	}
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::is_GetPduListFromOutletPattern_allowed()
+ *	Description : Execution allowed for GetPduListFromOutletPattern attribute
+ */
+//--------------------------------------------------------
+bool PduMapper::is_GetPduListFromOutletPattern_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Compare device state with not allowed states.
+	if (get_state()==Tango::FAULT ||
+		get_state()==Tango::INIT)
+	{
+	/*----- PROTECTED REGION ID(PduMapper::GetPduListFromOutletPatternStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::GetPduListFromOutletPatternStateAllowed
+		return false;
+	}
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::is_GetPduInfoFromName_allowed()
+ *	Description : Execution allowed for GetPduInfoFromName attribute
+ */
+//--------------------------------------------------------
+bool PduMapper::is_GetPduInfoFromName_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Compare device state with not allowed states.
+	if (get_state()==Tango::FAULT ||
+		get_state()==Tango::INIT)
+	{
+	/*----- PROTECTED REGION ID(PduMapper::GetPduInfoFromNameStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::GetPduInfoFromNameStateAllowed
+		return false;
+	}
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : PduMapper::is_GetOutletsListFromOutletPattern_allowed()
+ *	Description : Execution allowed for GetOutletsListFromOutletPattern attribute
+ */
+//--------------------------------------------------------
+bool PduMapper::is_GetOutletsListFromOutletPattern_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for GetOutletsListFromOutletPattern command.
+	/*----- PROTECTED REGION ID(PduMapper::GetOutletsListFromOutletPatternStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	PduMapper::GetOutletsListFromOutletPatternStateAllowed
+	return true;
+}
+
+
+/*----- PROTECTED REGION ID(PduMapper::PduMapperStateAllowed.AdditionalMethods) ENABLED START -----*/
+
+//	Additional Methods
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::PduMapperStateAllowed.AdditionalMethods
+
+}	//	End of namespace
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..27a0eba
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,86 @@
+/*----- PROTECTED REGION ID(PduMapper::main.cpp) ENABLED START -----*/
+//=============================================================================
+//
+// file :        main.cpp
+//
+// description : C++ source for the PduMapper device server main.
+//               The main rule is to initialise (and create) the Tango
+//               system and to create the DServerClass singleton.
+//               The main should be the same for every Tango device server.
+//
+// project :     
+//
+// 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/>.
+// 
+// $Author: alessandro.olivo $
+//
+// $Revision: 1.1.1.1 $
+// $Date: 2017-10-02 14:01:30 $
+//
+// $HeadURL:  $
+//
+//=============================================================================
+//                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
+	try
+	{
+		// Initialise the device server
+		//----------------------------------------
+		Tango::Util *tg = Tango::Util::init(argc,argv);
+
+		// Create the device server singleton 
+		//	which will create everything
+		//----------------------------------------
+		tg->server_init(false);
+
+		// Run the endless loop
+		//----------------------------------------
+		cout << "Ready to accept request" << endl;
+		tg->server_run();
+	}
+	catch (bad_alloc &)
+	{
+		cout << "Can't allocate memory to store device object !!!" << endl;
+		cout << "Exiting" << endl;
+	}
+	catch (CORBA::Exception &e)
+	{
+		Tango::Except::print_exception(e);
+		
+		cout << "Received a CORBA_Exception" << endl;
+		cout << "Exiting" << endl;
+	}
+	Tango::Util::instance()->server_cleanup();
+	return(0);
+}
+
+/*----- PROTECTED REGION END -----*/	//	PduMapper::main.cpp
-- 
GitLab