First steps#

First Tango device server#

You start with the simplest Tango device to control one of these coffee machines:

main.py#
from tango.server import Device

class MegaCoffee3k(Device):
    pass


if __name__ == "__main__":
    MegaCoffee3k.run_server()
MegaCoffee3k.xmi#
<?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://tango.org/pogo/PogoDsl">
  <classes name="MegaCoffee3k" pogoRevision="9.9">
    <description description="" title="Tango MegaCorp Coffee machines 3000 series" sourcePath="/Users/antjou/tango-src/tango-doc/source/tutorial/src/cpp/01" language="Cpp" filestogenerate="XMI   file,Code files,CMakeLists,Protected Regions,WindowsCMakeLists" license="LGPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="false" hasAbstractCommand="false" hasAbstractAttribute="false">
      <inheritances classname="Device_Impl" sourcePath=""/>
      <identification contact="at tango-megacorp.inc - software" author="software" emailDomain="tango-megacorp.inc" classFamily="Training" siteSpecific="" platform="All Platforms" bus="TCP/UDP" manufacturer="Tango MegaCorp" reference=""/>
    </description>
    <commands name="State" description="This command gets the device state (stored in its device_state data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
      <argin description="none">
        <type xsi:type="pogoDsl:VoidType"/>
      </argin>
      <argout description="Device state">
        <type xsi:type="pogoDsl:StateType"/>
      </argout>
      <status abstract="true" inherited="true" concrete="true"/>
    </commands>
    <commands name="Status" description="This command gets the device status (stored in its device_status data member) and returns it to the caller." execMethod="dev_status" displayLevel="OPERATOR" polledPeriod="0">
      <argin description="none">
        <type xsi:type="pogoDsl:VoidType"/>
      </argin>
      <argout description="Device status">
        <type xsi:type="pogoDsl:ConstStringType"/>
      </argout>
      <status abstract="true" inherited="true" concrete="true"/>
    </commands>
    <preferences docHome="./doc_html" makefileHome="/opt/homebrew/Caskroom/mambaforge/base/envs/pogo/share/pogo/preferences"/>
  </classes>
</pogoDsl:PogoSystem>
main.cpp#
/*----- PROTECTED REGION ID(MegaCoffee3k::main.cpp) ENABLED START -----*/
/* clang-format on */
//=============================================================================
//
// file :        main.cpp
//
// description : C++ source for the MegaCoffee3k device server main.
//               The main rule is to initialize (and create) the Tango
//               system and to create the DServerClass singleton.
//               The main should be the same for every Tango device server.
//
// project :     Tango MegaCorp Coffee machines 3000 series
//
// 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 Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================
#include <tango/tango.h>

// Check if crash reporting is used.
#if defined(ENABLE_CRASH_REPORT)
#  include <crashreporting/crash_report.h>
#else
#  define DECLARE_CRASH_HANDLER
#  define INSTALL_CRASH_HANDLER
#endif

DECLARE_CRASH_HANDLER

int main(int argc,char *argv[])
{
	INSTALL_CRASH_HANDLER
	Tango::Util *tg = nullptr;
	try
	{
		// Initialize the device server
		//----------------------------------------
		tg = Tango::Util::init(argc,argv);

		// Create the device server singleton
		//	which will create everything
		//----------------------------------------
		tg->server_init(false);

		// Run the endless loop
		//----------------------------------------
		std::cout << "Ready to accept request" << std::endl;
		tg->server_run();
	}
	catch (std::bad_alloc &)
	{
		std::cout << "Can't allocate memory to store device object !!!" << std::endl;
		std::cout << "Exiting" << std::endl;
	}
	catch (CORBA::Exception &e)
	{
		Tango::Except::print_exception(e);

		std::cout << "Received a CORBA_Exception" << std::endl;
		std::cout << "Exiting" << std::endl;
	}

	if(tg)
	{
		tg->server_cleanup();
	}
	return(0);
}

/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::main.cpp
MegaCoffee3kClass.h#
/*----- PROTECTED REGION ID(MegaCoffee3kClass.h) ENABLED START -----*/
/* clang-format on */
//=============================================================================
//
// file :        MegaCoffee3kClass.h
//
// description : Include for the MegaCoffee3k root class.
//               This class is the singleton class for
//                the MegaCoffee3k device class.
//               It contains all properties and methods which the
//               MegaCoffee3k requires only once e.g. the commands.
//
// project :     Tango MegaCorp Coffee machines 3000 series
//
// 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 Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#ifndef MegaCoffee3kClass_H
#define MegaCoffee3kClass_H

#include <tango/tango.h>
#include "MegaCoffee3k.h"

/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass.h


namespace MegaCoffee3k_ns
{
/*----- PROTECTED REGION ID(MegaCoffee3kClass::classes for dynamic creation) ENABLED START -----*/
/* clang-format on */

/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::classes for dynamic creation

/**
 *	The MegaCoffee3kClass singleton definition
 */

#ifdef _TG_WINDOWS_
class __declspec(dllexport)  MegaCoffee3kClass : public Tango::DeviceClass
#else
class MegaCoffee3kClass : public Tango::DeviceClass
#endif
{
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::Additional DServer data members) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::Additional DServer data members

	public:
		//	write class properties data members
		Tango::DbData	cl_prop;
		Tango::DbData	cl_def_prop;
		Tango::DbData	dev_def_prop;
		//	Method prototypes
		static MegaCoffee3kClass *init(const char *);
		static MegaCoffee3kClass *instance();
		~MegaCoffee3kClass();
		Tango::DbDatum	get_class_property(std::string &);
		Tango::DbDatum	get_default_device_property(std::string &);
		Tango::DbDatum	get_default_class_property(std::string &);

	protected:
		MegaCoffee3kClass(std::string &);
		static MegaCoffee3kClass *_instance;
		void command_factory();
		void attribute_factory(std::vector<Tango::Attr *> &);
		void pipe_factory();
		void write_class_property();
		void set_default_property();
		void get_class_property();
		std::string get_cvstag();
		std::string get_cvsroot();

	private:
		void device_factory(TANGO_UNUSED(const Tango::DevVarStringArray *));
		void create_static_attribute_list(std::vector<Tango::Attr *> &);
		void erase_dynamic_attributes(const Tango::DevVarStringArray *,std::vector<Tango::Attr *> &);
		std::vector<std::string>	defaultAttList;
		Tango::Attr *get_attr_object_by_name(std::vector<Tango::Attr *> &att_list, std::string attname);
};

}	//	End of namespace

#endif   //	MegaCoffee3k_H
MegaCoffee3kClass.cpp#
/*----- PROTECTED REGION ID(MegaCoffee3kClass.cpp) ENABLED START -----*/
/* clang-format on */
//=============================================================================
//
// file :        MegaCoffee3kClass.cpp
//
// description : C++ source for the MegaCoffee3kClass.
//               A singleton class derived from DeviceClass.
//               It implements the command and attribute list
//               and all properties and methods required
//               by the MegaCoffee3k once per process.
//
// project :     Tango MegaCorp Coffee machines 3000 series
//
// 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 Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#include "MegaCoffee3kClass.h"
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass.cpp

//-------------------------------------------------------------------
/**
 *	Create MegaCoffee3kClass singleton and
 *	return it in a C function for Python usage
 */
//-------------------------------------------------------------------
extern "C" {
#ifdef _TG_WINDOWS_

__declspec(dllexport)

#endif

	Tango::DeviceClass *_create_MegaCoffee3k_class(const char *name) {
		return MegaCoffee3k_ns::MegaCoffee3kClass::init(name);
	}
}

namespace MegaCoffee3k_ns
{
//===================================================================
//	Initialize pointer for singleton pattern
//===================================================================
MegaCoffee3kClass *MegaCoffee3kClass::_instance = NULL;

//===================================================================
//	Class constants
//===================================================================
//--------------------------------------------------------
/**
 * method : 		MegaCoffee3kClass::MegaCoffee3kClass(std::string &s)
 * description : 	constructor for the MegaCoffee3kClass
 *
 * @param s	The class name
 */
//--------------------------------------------------------
MegaCoffee3kClass::MegaCoffee3kClass(std::string &s):Tango::DeviceClass(s)
{
	TANGO_LOG_INFO << "Entering MegaCoffee3kClass constructor" << std::endl;
	set_default_property();
	write_class_property();

	/*----- PROTECTED REGION ID(MegaCoffee3kClass::constructor) ENABLED START -----*/
	/* clang-format on */
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::constructor

	TANGO_LOG_INFO << "Leaving MegaCoffee3kClass constructor" << std::endl;
}

//--------------------------------------------------------
/**
 * method : 		MegaCoffee3kClass::~MegaCoffee3kClass()
 * description : 	destructor for the MegaCoffee3kClass
 */
//--------------------------------------------------------
MegaCoffee3kClass::~MegaCoffee3kClass()
{
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::destructor) ENABLED START -----*/
	/* clang-format on */
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::destructor

	_instance = NULL;
}


//--------------------------------------------------------
/**
 * method : 		MegaCoffee3kClass::init
 * description : 	Create the object if not already done.
 *                  Otherwise, just return a pointer to the object
 *
 * @param	name	The class name
 */
//--------------------------------------------------------
MegaCoffee3kClass *MegaCoffee3kClass::init(const char *name)
{
	if (_instance == NULL)
	{
		try
		{
			std::string s(name);
			_instance = new MegaCoffee3kClass(s);
		}
		catch (std::bad_alloc &)
		{
			throw;
		}
	}
	return _instance;
}

//--------------------------------------------------------
/**
 * method : 		MegaCoffee3kClass::instance
 * description : 	Check if object already created,
 *                  and return a pointer to the object
 */
//--------------------------------------------------------
MegaCoffee3kClass *MegaCoffee3kClass::instance()
{
	if (_instance == NULL)
	{
		std::cerr << "Class is not initialized !!" << std::endl;
		exit(-1);
	}
	return _instance;
}



//===================================================================
//	Command execution method calls
//===================================================================

//===================================================================
//	Properties management
//===================================================================
//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::get_class_property()
 *	Description: Get the class property for specified name.
 */
//--------------------------------------------------------
Tango::DbDatum MegaCoffee3kClass::get_class_property(std::string &prop_name)
{
	for (unsigned int i=0 ; i<cl_prop.size() ; i++)
		if (cl_prop[i].name == prop_name)
			return cl_prop[i];
	//	if not found, returns  an empty DbDatum
	return Tango::DbDatum(prop_name);
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::get_default_device_property()
 *	Description: Return the default value for device property.
 */
//--------------------------------------------------------
Tango::DbDatum MegaCoffee3kClass::get_default_device_property(std::string &prop_name)
{
	for (unsigned int i=0 ; i<dev_def_prop.size() ; i++)
		if (dev_def_prop[i].name == prop_name)
			return dev_def_prop[i];
	//	if not found, return  an empty DbDatum
	return Tango::DbDatum(prop_name);
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::get_default_class_property()
 *	Description: Return the default value for class property.
 */
//--------------------------------------------------------
Tango::DbDatum MegaCoffee3kClass::get_default_class_property(std::string &prop_name)
{
	for (unsigned int i=0 ; i<cl_def_prop.size() ; i++)
		if (cl_def_prop[i].name == prop_name)
			return cl_def_prop[i];
	//	if not found, return  an empty DbDatum
	return Tango::DbDatum(prop_name);
}


//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::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 MegaCoffee3kClass::set_default_property()
{
	std::string	prop_name;
	std::string	prop_desc;
	std::string	prop_def;
	std::vector<std::string>	vect_data;

	//	Set Default Class Properties

	//	Set Default device Properties
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::write_class_property()
 *	Description: Set class description fields as property in database
 */
//--------------------------------------------------------
void MegaCoffee3kClass::write_class_property()
{
	//	First time, check if database used
	if (Tango::Util::_UseDb == false)
		return;

	Tango::DbData	data;
	std::string	classname = get_name();
	std::string	header;

	//	Put title
	Tango::DbDatum	title("ProjectTitle");
	std::string	str_title("Tango MegaCorp Coffee machines 3000 series");
	title << str_title;
	data.push_back(title);

	//	Put Description
	Tango::DbDatum	description("Description");
	std::vector<std::string>	str_desc;
	str_desc.push_back("");
	description << str_desc;
	data.push_back(description);

	//  Put inheritance
	Tango::DbDatum	inher_datum("InheritedFrom");
	std::vector<std::string> inheritance;
	inheritance.push_back("TANGO_BASE_CLASS");
	inher_datum << inheritance;
	data.push_back(inher_datum);

	//	Call database and and values
	get_db_class()->put_property(data);
}

//===================================================================
//	Factory methods
//===================================================================

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::device_factory()
 *	Description: Create the device object(s)
 *                and store them in the device list
 */
//--------------------------------------------------------
void MegaCoffee3kClass::device_factory(const Tango::DevVarStringArray *devlist_ptr)
{
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::device_factory_before) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::device_factory_before

	//	Create devices and add it into the device list
	for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
	{
		TANGO_LOG_DEBUG << "Device name : " << (*devlist_ptr)[i].in() << std::endl;
		device_list.push_back(new MegaCoffee3k(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
		MegaCoffee3k *dev = static_cast<MegaCoffee3k *>(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(MegaCoffee3kClass::device_factory_after) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::device_factory_after
}
//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::attribute_factory()
 *	Description: Create the attribute object(s)
 *                and store them in the attribute list
 */
//--------------------------------------------------------
void MegaCoffee3kClass::attribute_factory(std::vector<Tango::Attr *> &)
{
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::attribute_factory_before) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::attribute_factory_before

	//	Create a list of static attributes
	create_static_attribute_list(get_class_attr()->get_attr_list());
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::attribute_factory_after) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::attribute_factory_after
}
//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::pipe_factory()
 *	Description: Create the pipe object(s)
 *                and store them in the pipe list
 */
//--------------------------------------------------------
void MegaCoffee3kClass::pipe_factory()
{
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::pipe_factory_before) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::pipe_factory_before
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::pipe_factory_after) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::pipe_factory_after
}
//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::command_factory()
 *	Description: Create the command object(s)
 *                and store them in the command list
 */
//--------------------------------------------------------
void MegaCoffee3kClass::command_factory()
{
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::command_factory_before) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::command_factory_before


	/*----- PROTECTED REGION ID(MegaCoffee3kClass::command_factory_after) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::command_factory_after
}

//===================================================================
//	Dynamic attributes related methods
//===================================================================

//--------------------------------------------------------
/**
 * method : 		MegaCoffee3kClass::create_static_attribute_list
 * description : 	Create the a list of static attributes
 *
 * @param	att_list	the created attribute list
 */
//--------------------------------------------------------
void MegaCoffee3kClass::create_static_attribute_list(std::vector<Tango::Attr *> &att_list)
{
	for (unsigned long i=0 ; i<att_list.size() ; i++)
	{
		std::string att_name(att_list[i]->get_name());
		std::transform(att_name.begin(), att_name.end(), att_name.begin(), ::tolower);
		defaultAttList.push_back(att_name);
	}

	TANGO_LOG_INFO << defaultAttList.size() << " attributes in default list" << std::endl;

	/*----- PROTECTED REGION ID(MegaCoffee3kClass::create_static_att_list) ENABLED START -----*/
	/* clang-format on */
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::create_static_att_list
}


//--------------------------------------------------------
/**
 * method : 		MegaCoffee3kClass::erase_dynamic_attributes
 * description : 	delete the dynamic attributes if any.
 *
 * @param	devlist_ptr	the device list pointer
 * @param	list of all attributes
 */
//--------------------------------------------------------
void MegaCoffee3kClass::erase_dynamic_attributes(const Tango::DevVarStringArray *devlist_ptr, std::vector<Tango::Attr *> &att_list)
{
	Tango::Util *tg = Tango::Util::instance();

	for (unsigned long i=0 ; i<devlist_ptr->length() ; i++)
	{
		Tango::DeviceImpl *dev_impl = tg->get_device_by_name(((std::string)(*devlist_ptr)[i]).c_str());
		MegaCoffee3k *dev = static_cast<MegaCoffee3k *> (dev_impl);

		std::vector<Tango::Attribute *> &dev_att_list = dev->get_device_attr()->get_attribute_list();
		std::vector<Tango::Attribute *>::iterator ite_att;
		for (ite_att=dev_att_list.begin() ; ite_att != dev_att_list.end() ; ++ite_att)
		{
			std::string att_name((*ite_att)->get_name_lower());
			if ((att_name == "state") || (att_name == "status"))
				continue;
			std::vector<std::string>::iterator ite_str = find(defaultAttList.begin(), defaultAttList.end(), att_name);
			if (ite_str == defaultAttList.end())
			{
				TANGO_LOG_INFO << att_name << " is a UNWANTED dynamic attribute for device " << (*devlist_ptr)[i] << std::endl;
				Tango::Attribute &att = dev->get_device_attr()->get_attr_by_name(att_name.c_str());
				dev->remove_attribute(att_list[att.get_attr_idx()], true, false);
				--ite_att;
			}
		}
	}
	/*----- PROTECTED REGION ID(MegaCoffee3kClass::erase_dynamic_attributes) ENABLED START -----*/
	/* clang-format on */
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::erase_dynamic_attributes
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3kClass::get_attr_object_by_name()
 *	Description: returns Tango::Attr * object found by name
 */
//--------------------------------------------------------
Tango::Attr *MegaCoffee3kClass::get_attr_object_by_name(std::vector<Tango::Attr *> &att_list, std::string attname)
{
	std::vector<Tango::Attr *>::iterator it;
	for (it=att_list.begin() ; it<att_list.end() ; ++it)
		if ((*it)->get_name()==attname)
			return (*it);
	//	Attr does not exist
	return NULL;
}


/*----- PROTECTED REGION ID(MegaCoffee3kClass::Additional Methods) ENABLED START -----*/
/* clang-format on */
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3kClass::Additional Methods
} //	namespace
MegaCoffee3k.h#
/*----- PROTECTED REGION ID(MegaCoffee3k.h) ENABLED START -----*/
/* clang-format on */
//=============================================================================
//
// file :        MegaCoffee3k.h
//
// description : Include file for the MegaCoffee3k class
//
// project :     Tango MegaCorp Coffee machines 3000 series
//
// 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 Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#ifndef MegaCoffee3k_H
#define MegaCoffee3k_H

#include <tango/tango.h>

/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.h

#ifdef TANGO_LOG
	// cppTango after c934adea (Merge branch 'remove-cout-definition' into 'main', 2022-05-23)
	// nothing to do
#else
	// cppTango 9.3-backports and older
	#define TANGO_LOG       cout
	#define TANGO_LOG_INFO  cout2
	#define TANGO_LOG_DEBUG cout3
#endif // TANGO_LOG

/**
 *  MegaCoffee3k class description:
 *
 */


namespace MegaCoffee3k_ns
{
/*----- PROTECTED REGION ID(MegaCoffee3k::Additional Class Declarations) ENABLED START -----*/
/* clang-format on */
//	Additional Class Declarations
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::Additional Class Declarations

class MegaCoffee3k : public TANGO_BASE_CLASS
{

/*----- PROTECTED REGION ID(MegaCoffee3k::Data Members) ENABLED START -----*/
/* clang-format on */
//	Add your own data members
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::Data Members



//	Constructors and destructors
public:
	/**
	 * Constructs a newly device object.
	 *
	 *	@param cl	Class.
	 *	@param s 	Device Name
	 */
	MegaCoffee3k(Tango::DeviceClass *cl,std::string &s);
	/**
	 * Constructs a newly device object.
	 *
	 *	@param cl	Class.
	 *	@param s 	Device Name
	 */
	MegaCoffee3k(Tango::DeviceClass *cl,const char *s);
	/**
	 * Constructs a newly device object.
	 *
	 *	@param cl	Class.
	 *	@param s 	Device name
	 *	@param d	Device description.
	 */
	MegaCoffee3k(Tango::DeviceClass *cl,const char *s,const char *d);
	/**
	 * The device object destructor.
	 */
	~MegaCoffee3k();


//	Miscellaneous methods
public:
	/*
	 *	will be called at device destruction or at init command.
	 */
	void delete_device();
	/*
	 *	Initialize the device
	 */
	virtual void init_device();
	/*
	 *	Always executed method before execution command method.
	 */
	virtual void always_executed_hook();


//	Attribute methods
public:
	//--------------------------------------------------------
	/*
	 *	Method     : MegaCoffee3k::read_attr_hardware()
	 *	Description: Hardware acquisition for attributes.
	 */
	//--------------------------------------------------------
	virtual void read_attr_hardware(std::vector<long> &attr_list);


	//--------------------------------------------------------
	/**
	 *	Method     : MegaCoffee3k::add_dynamic_attributes()
	 *	Description: Add dynamic attributes if any.
	 */
	//--------------------------------------------------------
	void add_dynamic_attributes();




//	Command related methods
public:


	//--------------------------------------------------------
	/**
	 *	Method     : MegaCoffee3k::add_dynamic_commands()
	 *	Description: Add dynamic commands if any.
	 */
	//--------------------------------------------------------
	void add_dynamic_commands();

/*----- PROTECTED REGION ID(MegaCoffee3k::Additional Method prototypes) ENABLED START -----*/
/* clang-format on */
//	Additional Method prototypes
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::Additional Method prototypes
};

/*----- PROTECTED REGION ID(MegaCoffee3k::Additional Classes Definitions) ENABLED START -----*/
/* clang-format on */
//	Additional Classes Definitions
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::Additional Classes Definitions

}	//	End of namespace

#endif   //	MegaCoffee3k_H
MegaCoffee3k.cpp#
/*----- PROTECTED REGION ID(MegaCoffee3k.cpp) ENABLED START -----*/
/* clang-format on */
//=============================================================================
//
// file :        MegaCoffee3k.cpp
//
// description : C++ source for the MegaCoffee3k 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
//               MegaCoffee3k are implemented in this file.
//
// project :     Tango MegaCorp Coffee machines 3000 series
//
// 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 Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================


#include "MegaCoffee3k.h"
#include "MegaCoffee3kClass.h"
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.cpp

/**
 *  MegaCoffee3k class description:
 *
 */

//================================================================
//  The following table gives the correspondence
//  between command and method names.
//
//  Command name  |  Method name
//================================================================
//  State         |  Inherited (no method)
//  Status        |  Inherited (no method)
//================================================================

//================================================================
//  Attributes managed is:
//================================================================
//================================================================

namespace MegaCoffee3k_ns
{
/*----- PROTECTED REGION ID(MegaCoffee3k::namespace_starting) ENABLED START -----*/
/* clang-format on */
//	static initializations
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::namespace_starting

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3k::MegaCoffee3k()
 *	Description: Constructors for a Tango device
 *                implementing the classMegaCoffee3k
 */
//--------------------------------------------------------
MegaCoffee3k::MegaCoffee3k(Tango::DeviceClass *cl, std::string &s)
 : TANGO_BASE_CLASS(cl, s.c_str())
{
	/*----- PROTECTED REGION ID(MegaCoffee3k::constructor_1) ENABLED START -----*/
	/* clang-format on */
	init_device();
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::constructor_1
}
//--------------------------------------------------------
MegaCoffee3k::MegaCoffee3k(Tango::DeviceClass *cl, const char *s)
 : TANGO_BASE_CLASS(cl, s)
{
	/*----- PROTECTED REGION ID(MegaCoffee3k::constructor_2) ENABLED START -----*/
	/* clang-format on */
	init_device();
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::constructor_2
}
//--------------------------------------------------------
MegaCoffee3k::MegaCoffee3k(Tango::DeviceClass *cl, const char *s, const char *d)
 : TANGO_BASE_CLASS(cl, s, d)
{
	/*----- PROTECTED REGION ID(MegaCoffee3k::constructor_3) ENABLED START -----*/
	/* clang-format on */
	init_device();
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::constructor_3
}
//--------------------------------------------------------
MegaCoffee3k::~MegaCoffee3k()
{
	delete_device();
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3k::delete_device()
 *	Description: will be called at device destruction or at init command
 */
//--------------------------------------------------------
void MegaCoffee3k::delete_device()
{
	DEBUG_STREAM << "MegaCoffee3k::delete_device() " << device_name << std::endl;
	/*----- PROTECTED REGION ID(MegaCoffee3k::delete_device) ENABLED START -----*/
	/* clang-format on */
	//	Delete device allocated objects
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::delete_device
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3k::init_device()
 *	Description: will be called at device initialization.
 */
//--------------------------------------------------------
void MegaCoffee3k::init_device()
{
	DEBUG_STREAM << "MegaCoffee3k::init_device() create device " << device_name << std::endl;
	/*----- PROTECTED REGION ID(MegaCoffee3k::init_device_before) ENABLED START -----*/
	/* clang-format on */
	//	Initialization before get_device_property() call
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::init_device_before

	//	No device property to be read from database

	/*----- PROTECTED REGION ID(MegaCoffee3k::init_device) ENABLED START -----*/
	/* clang-format on */
	//	Initialize device
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::init_device
}


//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3k::always_executed_hook()
 *	Description: method always executed before any command is executed
 */
//--------------------------------------------------------
void MegaCoffee3k::always_executed_hook()
{
	DEBUG_STREAM << "MegaCoffee3k::always_executed_hook()  " << device_name << std::endl;
	/*----- PROTECTED REGION ID(MegaCoffee3k::always_executed_hook) ENABLED START -----*/
	/* clang-format on */
	//	code always executed before all requests
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::always_executed_hook
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3k::read_attr_hardware()
 *	Description: Hardware acquisition for attributes
 */
//--------------------------------------------------------
void MegaCoffee3k::read_attr_hardware(TANGO_UNUSED(std::vector<long> &attr_list))
{
	DEBUG_STREAM << "MegaCoffee3k::read_attr_hardware(std::vector<long> &attr_list) entering... " << std::endl;
	/*----- PROTECTED REGION ID(MegaCoffee3k::read_attr_hardware) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::read_attr_hardware
}


//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3k::add_dynamic_attributes()
 *	Description: Create the dynamic attributes if any
 *                for specified device.
 */
//--------------------------------------------------------
void MegaCoffee3k::add_dynamic_attributes()
{
	/*----- PROTECTED REGION ID(MegaCoffee3k::add_dynamic_attributes) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code to create and add dynamic attributes if any
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::add_dynamic_attributes
}

//--------------------------------------------------------
/**
 *	Method     : MegaCoffee3k::add_dynamic_commands()
 *	Description: Create the dynamic commands if any
 *                for specified device.
 */
//--------------------------------------------------------
void MegaCoffee3k::add_dynamic_commands()
{
	/*----- PROTECTED REGION ID(MegaCoffee3k::add_dynamic_commands) ENABLED START -----*/
	/* clang-format on */
	//	Add your own code to create and add dynamic commands if any
	/* clang-format off */
	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::add_dynamic_commands
}

/*----- PROTECTED REGION ID(MegaCoffee3k::namespace_ending) ENABLED START -----*/
/* clang-format on */
//	Additional Methods
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::namespace_ending
} //	namespace
MegaCoffee3kStateMachine.cpp#
/*----- PROTECTED REGION ID(MegaCoffee3kStateMachine.cpp) ENABLED START -----*/
/* clang-format on */
//=============================================================================
//
// file :        MegaCoffee3kStateMachine.cpp
//
// description : State machine file for the MegaCoffee3k class
//
// project :     Tango MegaCorp Coffee machines 3000 series
//
// 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 Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================

#include "MegaCoffee3k.h"

/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::MegaCoffee3kStateMachine.cpp

//================================================================
//  States  |  Description
//================================================================


namespace MegaCoffee3k_ns
{
//=================================================
//		Attributes Allowed Methods
//=================================================


//=================================================
//		Commands Allowed Methods
//=================================================


/*----- PROTECTED REGION ID(MegaCoffee3k::MegaCoffee3kStateAllowed.AdditionalMethods) ENABLED START -----*/
/* clang-format on */
//	Additional Methods
/* clang-format off */
/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k::MegaCoffee3kStateAllowed.AdditionalMethods

}	//	End of namespace
CMakeLists.txt#
#=============================================================================
#
# file :        CMakeLists.txt
#
# description : File to generate a TANGO device server using cmake.
#
# project :     MegaCoffee3k
#
#=============================================================================
#                This file is generated by POGO
#        (Program Obviously used to Generate tango Object)
#=============================================================================
#
#

cmake_minimum_required (VERSION 3.18...3.26 FATAL_ERROR)
set(CMAKE_SKIP_RPATH true)

# Windows cmakelists

# MAKE_ENV is the path to find the common environment to build the project
#
if (DEFINED ENV{MAKE_ENV})
    set(MAKE_ENV $ENV{MAKE_ENV})
else()
    set(MAKE_ENV /opt/homebrew/Caskroom/mambaforge/base/envs/pogo/share/pogo/preferences)
endif()
#
# Project definitions
#
project(MegaCoffee3k)

#
# optional compiler flags
#
set(CXXFLAGS_USER -g)


#
# Get global information
#
include(CmakeTangoWin.cmake)

#
# Files for MegaCoffee3k TANGO class
#
set(MegaCoffee3k MegaCoffee3k)
set(MegaCoffee3k_INCLUDE ${CMAKE_SOURCE_DIR})
set(MegaCoffee3k_SRC  ${MegaCoffee3k}.cpp
                       ${MegaCoffee3k}Class.cpp
                       ${MegaCoffee3k}StateMachine.cpp)


#
# User additional include, link folders/libraries and source files
#
set(USER_INCL_DIR )
set(USER_LIB_DIR )
set(USER_LIBS )
set(USER_SRC_FILES )

#
# Set global info and include directories
#
set(ALL_CLASS_INCLUDE  ${MegaCoffee3k_INCLUDE}  ${USER_INCL_DIR})
set(SERVER_SRC ${MegaCoffee3k_SRC}  ${USER_SRC_FILES} ClassFactory.cpp main.cpp)
include_directories(${ALL_CLASS_INCLUDE}  ${USER_INCL_DIR} ${TANGO_INCLUDES})
link_directories(${TANGO_LNK_DIR})

#
# Device Server generation
#
set(SERVER_NAME MegaCoffee3k)
add_executable(MegaCoffee3k ${SERVER_SRC})
target_link_libraries(MegaCoffee3k PUBLIC ${TANGO_LIBS} ${WIN_LIBS} ${ZMQ_LIB})
# Cpack target
install(TARGETS MegaCoffee3k
	RUNTIME DESTINATION bin
	LIBRARY DESTINATION bin
	ARCHIVE DESTINATION bin)
MegaCoffee3k.xmi#
<?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://tango.org/pogo/PogoDsl">
  <classes name="MegaCoffee3k" pogoRevision="9.9">
    <description description="" title="Tango MegaCorp Coffee machines 3000 series" sourcePath="/Users/antjou/tango-src/tango-doc/source/tutorial/src/java/01" language="Java" filestogenerate="XMI   file,Code files,Makefile,Protected Regions,pom.xml" license="LGPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="false" hasAbstractCommand="false" hasAbstractAttribute="false">
      <inheritances classname="Device_Impl" sourcePath=""/>
      <identification contact="at tango-megacorp.inc - software" author="software" emailDomain="tango-megacorp.inc" classFamily="Training" siteSpecific="" platform="All Platforms" bus="TCP/UDP" manufacturer="Tango MegaCorp" reference=""/>
    </description>
    <commands name="State" description="This command gets the device state (stored in its device_state data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0">
      <argin description="none">
        <type xsi:type="pogoDsl:VoidType"/>
      </argin>
      <argout description="Device state">
        <type xsi:type="pogoDsl:StateType"/>
      </argout>
      <status abstract="true" inherited="true" concrete="true"/>
    </commands>
    <commands name="Status" description="This command gets the device status (stored in its device_status data member) and returns it to the caller." execMethod="dev_status" displayLevel="OPERATOR" polledPeriod="0">
      <argin description="none">
        <type xsi:type="pogoDsl:VoidType"/>
      </argin>
      <argout description="Device status">
        <type xsi:type="pogoDsl:ConstStringType"/>
      </argout>
      <status abstract="true" inherited="true" concrete="true"/>
    </commands>
    <preferences docHome="./doc_html" makefileHome="/opt/homebrew/Caskroom/mambaforge/base/envs/pogo/share/pogo/preferences"/>
  </classes>
</pogoDsl:PogoSystem>
MegaCoffee3k.java#
/*----- PROTECTED REGION ID(MegaCoffee3k.java) ENABLED START -----*/
//=============================================================================
//
// file :        MegaCoffee3k.java
//
// description : Java source for the MegaCoffee3k 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
//               MegaCoffee3k are implemented in this file.
//
// project :     Tango MegaCorp Coffee machines 3000 series
//
// 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 Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Tango.  If not, see <http://www.gnu.org/licenses/>.
//
//
//
//=============================================================================
//                This file is generated by POGO
//        (Program Obviously used to Generate tango Object)
//=============================================================================

/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.java

package org.tango.megacoffee3k;

/*----- PROTECTED REGION ID(MegaCoffee3k.imports) ENABLED START -----*/
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
import org.tango.DeviceState;
import org.tango.server.InvocationContext;
import org.tango.server.ServerManager;
import org.tango.server.annotation.AroundInvoke;
import org.tango.server.annotation.Attribute;
import org.tango.server.annotation.AttributeProperties;
import org.tango.server.annotation.ClassProperty;
import org.tango.server.annotation.Command;
import org.tango.server.annotation.Delete;
import org.tango.server.annotation.Device;
import org.tango.server.annotation.DeviceProperty;
import org.tango.server.annotation.DynamicManagement;
import org.tango.server.annotation.Init;
import org.tango.server.annotation.State;
import org.tango.server.annotation.StateMachine;
import org.tango.server.annotation.Status;
import org.tango.server.annotation.DeviceManagement;
import org.tango.server.annotation.Pipe;
import org.tango.server.attribute.ForwardedAttribute;import org.tango.server.pipe.PipeValue;
import org.tango.server.dynamic.DynamicManager;
import org.tango.server.device.DeviceManager;
import org.tango.server.dynamic.DynamicManager;
import org.tango.server.events.EventManager;
import org.tango.server.events.EventType;
import org.tango.utils.DevFailedUtils;

//	Import Tango IDL types
import fr.esrf.Tango.*;
import fr.esrf.TangoDs.Except;
import fr.esrf.TangoApi.PipeBlob;
import fr.esrf.TangoApi.PipeDataElement;

/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.imports

/**
 *  MegaCoffee3k class description:
 *
 */

@Device
public class MegaCoffee3k {

	protected static final Logger logger = LoggerFactory.getLogger(MegaCoffee3k.class);
	protected static final XLogger xlogger = XLoggerFactory.getXLogger(MegaCoffee3k.class);
	//========================================================
	//	Programmer's data members
	//========================================================
    /*----- PROTECTED REGION ID(MegaCoffee3k.variables) ENABLED START -----*/

    //	Put static variables here

    /*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.variables
	/*----- PROTECTED REGION ID(MegaCoffee3k.private) ENABLED START -----*/

	//	Put private variables here

	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.private

	//========================================================
	//	Property data members and related methods
	//========================================================


	//========================================================
	//	Miscellaneous methods
	//========================================================
	/**
	 * Initialize the device.
	 *
	 * @throws DevFailed if something fails during the device initialization.
	 */
	@Init(lazyLoading = false)
	public void initDevice() throws DevFailed {
		xlogger.entry();
		logger.debug("init device " + deviceManager.getName());
		/*----- PROTECTED REGION ID(MegaCoffee3k.initDevice) ENABLED START -----*/

		//	Put your device initialization code here

		/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.initDevice
		xlogger.exit();
	}

	/**
	 * all resources may be closed here. Collections may be also cleared.
	 *
	 * @throws DevFailed if something fails during the device object deletion.
	 */
	@Delete
	public void deleteDevice() throws DevFailed {
		xlogger.entry();
		/*----- PROTECTED REGION ID(MegaCoffee3k.deleteDevice) ENABLED START -----*/

		//	Put your device clearing code here

		/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.deleteDevice
		xlogger.exit();
	}

	/**
	 * Method called before and after command and attribute calls.
	 * @param ctx the invocation context
	 * @throws DevFailed if something fails during this method execution.
	 */
	@AroundInvoke
	public void aroundInvoke(final InvocationContext ctx) throws DevFailed {
		xlogger.entry();
			/*----- PROTECTED REGION ID(MegaCoffee3k.aroundInvoke) ENABLED START -----*/

			//	Put aroundInvoke code here

			/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.aroundInvoke
		xlogger.exit();
	}


	/**
	 * dynamic command and attribute management. Will be injected by the framework.
	 */
	@DynamicManagement
	protected DynamicManager dynamicManager;
	/**
	 * @param dynamicManager the DynamicManager instance
	 * @throws DevFailed if something fails during this method execution.
	 */
	public void setDynamicManager(final DynamicManager dynamicManager) throws DevFailed {
		this.dynamicManager = dynamicManager;
		/*----- PROTECTED REGION ID(MegaCoffee3k.setDynamicManager) ENABLED START -----*/

		//	Put your code here

		/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.setDynamicManager
	}

	/**
	 * Device management. Will be injected by the framework.
	 */
	@DeviceManagement
	DeviceManager deviceManager;
	public void setDeviceManager(DeviceManager deviceManager){
		this.deviceManager= deviceManager ;
	}




	//========================================================
	//	Command data members and related methods
	//========================================================
	/**
	 * The state of the device
	*/
	@State
	private DevState state = DevState.UNKNOWN;
	/**
	 * Execute command "State".
	 * description: This command gets the device state (stored in its 'state' data member) and returns it to the caller.
	 * @return Device state
	 * @throws DevFailed if command execution failed.
	 */
	public final DevState getState() throws DevFailed {
		/*----- PROTECTED REGION ID(MegaCoffee3k.getState) ENABLED START -----*/

		//	Put state code here

		/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.getState
		return state;
	}
	/**
	 * Set the device state
	 * @param state the new device state
	 */
	public void setState(final DevState state) {
		this.state = state;
	}

	/**
	 * The status of the device
	 */
	@Status
	private String status = "Server is starting. The device state is unknown";
	/**
	 * Execute command "Status".
	 * description: This command gets the device status (stored in its 'status' data member) and returns it to the caller.
	 * @return Device status
	 * @throws DevFailed if command execution failed.
	 */
	public final String getStatus() throws DevFailed {
		/*----- PROTECTED REGION ID(MegaCoffee3k.getStatus) ENABLED START -----*/

		//	Put status code here

		/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.getStatus
		return status;
	}
	/**
	 * Set the device status
	 * @param status the new device status
	 */
	public void setStatus(final String status) {
		this.status = status;
	}


	//========================================================
	//	Programmer's methods
	//========================================================
	/*----- PROTECTED REGION ID(MegaCoffee3k.methods) ENABLED START -----*/

	//	Put your own methods here

	/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.methods






	/**
	 * Starts the server.
	 * @param args program arguments (instance_name [-v[trace level]]  [-nodb [-dlist <device name list>] [-file=fileName]])
	 */
	public static void main(final String[] args) {
		/*----- PROTECTED REGION ID(MegaCoffee3k.main) ENABLED START -----*/

		/*----- PROTECTED REGION END -----*/	//	MegaCoffee3k.main
		ServerManager.getInstance().start(args, MegaCoffee3k.class);
		System.out.println("------- Started -------------");
	}
}

For the Python example, copy that to a file main.py.

Make sure your Pixi shell is active, so the prompt should look something like this.

(tango-tut) $

Now you can run your first Tango device server, using PyTango’s test_context utility:

(tango-tut) $ python -m tango.test_context main.MegaCoffee3k --host 127.0.0.1

You see the output:

Ready to accept request
MegaCoffee3k started on port 8888 with properties {}
Device access: tango://127.0.0.1:8888/test/nodb/megacoffee3k#dbase=no
Server access: tango://127.0.0.1:8888/dserver/MegaCoffee3k/megacoffee3k#dbase=no

The Ready to accept request line tells you that device server has started up.

The lines after that are from the “test context” used to launch it. You’ll use the cryptic Device access part in the next section.

Hint

Don’t worry about the notifd warning, if you see it. It isn’t used in newer Tango systems.

First Tango client#

Tango uses a distributed client-server architecture. Now that you have your MegaCoffee3k device server running, you need to connect a client.

Start a new terminal, so that the server keeps running in the old terminal. Again, activate your environment.

$ pixi shell
(tango-tut) $ python

We use PyTango, and the Device access Tango resource locator, tango://127.0.0.1:8888/test/nodb/megacoffee3k#dbase=no to connect our client, a Tango Device Proxy.

>>> import tango
>>> dp = tango.DeviceProxy("tango://127.0.0.1:8888/test/nodb/megacoffee3k#dbase=no")
>>> dp.ping()
382
>>> dp.State()
tango._tango.DevState.UNKNOWN
>>> dp.Status()
'The device is in UNKNOWN state.'
>>>

It works! That was super east, but it isn’t super useful yet. Read on!

Hint

If you’re wondering, the value 382 is the ping response time in microseconds.

Finishing up#

You can use the keyboard combination Ctrl+C to end the Tango device server application.

Can't create notifd event supplier. Notifd event not available
Ready to accept request
MegaCoffee3k started on port 8888 with properties {}
Device access: tango://127.0.0.1:8888/test/nodb/megacoffee3k#dbase=no
Server access: tango://127.0.0.1:8888/dserver/MegaCoffee3k/megacoffee3k#dbase=no
^CDone
(tango-tut) $

Similarly, you can exit the Python interpreter console when you are done with the client.