From 2da801aa3099f09d003ca92336e0b78d37d7246a Mon Sep 17 00:00:00 2001
From: gscalamera <graziano.scalamera@elettra.eu>
Date: Fri, 24 Feb 2017 12:28:43 +0100
Subject: [PATCH] Transformed alarm attributes to DevEnum and added formula
 attributes

---
 src/Alarm.cpp             |  93 +++++++++++++++++++++++++++++----
 src/Alarm.h               |  31 +++++++++--
 src/Alarm.xmi             |  23 +++++++--
 src/AlarmClass.h          |  17 +++++-
 src/AlarmDynAttrUtils.cpp | 106 +++++++++++++++++++++++++++++++++++---
 src/AlarmStateMachine.cpp |  16 ++++++
 src/alarm_table.h         |   4 +-
 7 files changed, 265 insertions(+), 25 deletions(-)

diff --git a/src/Alarm.cpp b/src/Alarm.cpp
index 5389647..7c66d61 100644
--- a/src/Alarm.cpp
+++ b/src/Alarm.cpp
@@ -1105,14 +1105,14 @@ void Alarm::read_alarm(Tango::Attribute &attr)
  *	Read attribute AlarmState related method
  *	Description: 
  *
- *	Data type:	Tango::DevBoolean
+ *	Data type:	Tango::DevEnum (AlarmStateEnum)
  *	Attr type:	Scalar
  */
 //--------------------------------------------------------
 void Alarm::read_AlarmState(Tango::Attribute &attr)
 {
 	DEBUG_STREAM << "Alarm::read_AlarmState(Tango::Attribute &attr) entering... " << endl;
-	Tango::DevBoolean	*att_value = get_AlarmState_data_ptr(attr.get_name());
+	Tango::DevEnum	*att_value = get_AlarmState_data_ptr(attr.get_name());
 	/*----- PROTECTED REGION ID(Alarm::read_AlarmState) ENABLED START -----*/
 	string reason("");
 	string desc("");
@@ -1166,6 +1166,25 @@ void Alarm::read_AlarmState(Tango::Attribute &attr)
 	/*----- PROTECTED REGION END -----*/	//	Alarm::read_AlarmState
 }
 //--------------------------------------------------------
+/**
+ *	Read attribute AlarmFormula related method
+ *	Description: 
+ *
+ *	Data type:	Tango::DevString
+ *	Attr type:	Scalar
+ */
+//--------------------------------------------------------
+void Alarm::read_AlarmFormula(Tango::Attribute &attr)
+{
+	DEBUG_STREAM << "Alarm::read_AlarmFormula(Tango::Attribute &attr) entering... " << endl;
+	Tango::DevString	*att_value = get_AlarmFormula_data_ptr(attr.get_name());
+	/*----- PROTECTED REGION ID(Alarm::read_AlarmFormula) ENABLED START -----*/
+	//	Set the attribute value
+	attr.set_value(att_value);
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::read_AlarmFormula
+}
+//--------------------------------------------------------
 /**
  *	Method      : Alarm::add_dynamic_attributes()
  *	Description : Create the dynamic attributes if any
@@ -1177,6 +1196,7 @@ void Alarm::add_dynamic_attributes()
 	//	Example to add dynamic attribute:
 	//	Copy inside the following protected area to create instance(s) at startup.
 	//	add_AlarmState_dynamic_attribute("MyAlarmStateAttribute");
+	//	add_AlarmFormula_dynamic_attribute("MyAlarmFormulaAttribute");
 	
 	/*----- PROTECTED REGION ID(Alarm::add_dynamic_attributes) ENABLED START -----*/
 	
@@ -1192,8 +1212,13 @@ void Alarm::add_dynamic_attributes()
 			i != alarms.v_alarm.end(); i++)
 		{
 			add_AlarmState_dynamic_attribute(i->second.attr_name);
-			Tango::DevBoolean *attr_value = get_AlarmState_data_ptr(i->second.attr_name);
+			Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);
 			i->second.attr_value = attr_value;
+			i->second.attr_name_formula = i->second.attr_name + string("Formula");
+			add_AlarmFormula_dynamic_attribute(i->second.attr_name_formula);
+			Tango::DevString *attr_value_formula = get_AlarmFormula_data_ptr(i->second.attr_name_formula);
+			*attr_value_formula = CORBA::string_dup(i->second.formula.c_str());
+			i->second.attr_value_formula = attr_value_formula;
 		}
 	}
 #ifndef _RW_LOCK
@@ -1201,7 +1226,6 @@ void Alarm::add_dynamic_attributes()
 #else
 	alarms.vlock->readerOut();
 #endif
-
 	
 	/*----- PROTECTED REGION END -----*/	//	Alarm::add_dynamic_attributes
 }
@@ -1247,8 +1271,44 @@ void Alarm::ack(const Tango::DevVarStringArray *argin)
 			{
 				alarms.log_alarm_db(TYPE_LOG_STATUS, gettime(), found->name, found->stat, ACK, 
 						"", 0, "", "", "", "", -1);
+
+				Tango::DevEnum *attr_value = get_AlarmState_data_ptr(i->second.attr_name);
+				//TODO: if not _SHLVD, _DSUPR, _OOSRV
+				if((i->second.stat == S_NORMAL) && i->second.ack == ACK)
+					*attr_value = _NORM;
+				else if((i->second.stat == S_ALARM) && i->second.ack == NOT_ACK)
+					*attr_value = _UNACK;
+				else if((i->second.stat == S_ALARM) && i->second.ack == ACK)
+					*attr_value = _ACKED;
+				else if((i->second.stat == S_NORMAL) && i->second.ack == NOT_ACK)
+					*attr_value = _RTNUN;
+				try
+				{	//DevFailed for push events
+					if(i->second.ex_reason.length() == 0)
+					{
+						timeval now;
+						gettimeofday(&now, NULL);
+						push_change_event(i->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false);
+						push_archive_event(i->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)i->second.quality, 1/*size*/, 0, false);
+					}
+					else
+					{
+						Tango::DevErrorList errors(1);
+						errors.length(1);
+						errors[0].desc = CORBA::string_dup(i->second.ex_desc.c_str());
+						errors[0].severity = Tango::ERR;
+						errors[0].reason = CORBA::string_dup(i->second.ex_reason.c_str());
+						errors[0].origin = CORBA::string_dup(i->second.ex_origin.c_str());
+						Tango::DevFailed except(errors);
+						push_change_event(i->second.attr_name, &except);
+						push_archive_event(i->second.attr_name, &except);
+					}
+				} catch(Tango::DevFailed & ex)
+				{
+					WARN_STREAM << "Alarm::"<<__func__<<": EXCEPTION PUSHING EVENTS: " << ex.errors[0].desc << endl;
+				}
 			}
-			found->ack = ACK;		
+			found->ack = ACK;
 		} else {
 			internallock->readerIn();
 			found = find(internal.begin(), internal.end(), *si);
@@ -2344,8 +2404,13 @@ void Alarm::load_alarm(string alarm_string, alarm_t &alm, vector<string> &evn)
 				(const char*)"Alarm::load_alarm()", Tango::ERR);
 	}
 	add_AlarmState_dynamic_attribute(alm.attr_name);
-	Tango::DevBoolean *attr_value = get_AlarmState_data_ptr(alm.attr_name);
+	Tango::DevEnum *attr_value = get_AlarmState_data_ptr(alm.attr_name);
 	alm.attr_value = attr_value;
+	alm.attr_name_formula = alm.attr_name + string("Formula");
+	add_AlarmFormula_dynamic_attribute(alm.attr_name_formula);
+	Tango::DevString *attr_value_formula = get_AlarmFormula_data_ptr(alm.attr_name_formula);
+	*attr_value_formula = CORBA::string_dup(alm.formula.c_str());
+	alm.attr_value_formula = attr_value_formula;
 	if (alarms.exist(alm.name)) {
 		ostringstream o;
 		o << "Alarm::load_alarm(): alarm '" << alm.name << "' already exist" << ends;
@@ -2786,16 +2851,24 @@ bool Alarm::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal ts)
 			res = eval_formula(it->second.formula_tree, attr_values);
 				DEBUG_STREAM << "Alarm::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << res.value << " quality=" << res.quality << endl;
 				changed = alarms.update(tmpname, ts, res, attr_values, it->second.grp2str(), it->second.msg, it->second.formula); 		//update internal structure and log to db
-				Tango::DevBoolean *attr_value = get_AlarmState_data_ptr(it->second.attr_name);
-				*attr_value = (it->second.stat == S_ALARM);
+				Tango::DevEnum *attr_value = get_AlarmState_data_ptr(it->second.attr_name);
+				//TODO: if not _SHLVD, _DSUPR, _OOSRV
+				if((it->second.stat == S_NORMAL) && it->second.ack == ACK)
+					*attr_value = _NORM;
+				else if((it->second.stat == S_ALARM) && it->second.ack == NOT_ACK)
+					*attr_value = _UNACK;
+				else if((it->second.stat == S_ALARM) && it->second.ack == ACK)
+					*attr_value = _ACKED;
+				else if((it->second.stat == S_NORMAL) && it->second.ack == NOT_ACK)
+					*attr_value = _RTNUN;
 			try
 			{	//DevFailed for push events
 				if(it->second.ex_reason.length() == 0)
 				{
 					timeval now;
 					gettimeofday(&now, NULL);
-					push_change_event(it->second.attr_name,(Tango::DevBoolean *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false);
-					push_archive_event(it->second.attr_name,(Tango::DevBoolean *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false);
+					push_change_event(it->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false);
+					push_archive_event(it->second.attr_name,(Tango::DevEnum *)attr_value,now,(Tango::AttrQuality)it->second.quality, 1/*size*/, 0, false);
 				}
 				else
 				{
diff --git a/src/Alarm.h b/src/Alarm.h
index 39e2af9..7cf0aa0 100644
--- a/src/Alarm.h
+++ b/src/Alarm.h
@@ -77,6 +77,17 @@ class update_thread;
 
 namespace Alarm_ns
 {
+enum _AlarmStateEnum {
+	_NORM,
+	_UNACK,
+	_ACKED,
+	_RTNUN,
+	_SHLVD,
+	_DSUPR,
+	_OOSRV,
+} ;
+typedef _AlarmStateEnum AlarmStateEnum;
+
 /*----- PROTECTED REGION ID(Alarm::Additional Class Declarations) ENABLED START -----*/
 
 //	Additional Class Declarations
@@ -204,15 +215,29 @@ public:
 	 *	Attribute AlarmState related methods
 	 *	Description: 
 	 *
-	 *	Data type:	Tango::DevBoolean
+	 *	Data type:	Tango::DevEnum
 	 *	Attr type:	Scalar
 	 */
 	virtual void read_AlarmState(Tango::Attribute &attr);
 	virtual bool is_AlarmState_allowed(Tango::AttReqType type);
 	void add_AlarmState_dynamic_attribute(string attname);
 	void remove_AlarmState_dynamic_attribute(string attname);
-	Tango::DevBoolean *get_AlarmState_data_ptr(string &name);
-	map<string,Tango::DevBoolean>	   AlarmState_data;
+	Tango::DevEnum *get_AlarmState_data_ptr(string &name);
+	map<string,Tango::DevEnum>	   AlarmState_data;
+
+	/**
+	 *	Attribute AlarmFormula related methods
+	 *	Description: 
+	 *
+	 *	Data type:	Tango::DevString
+	 *	Attr type:	Scalar
+	 */
+	virtual void read_AlarmFormula(Tango::Attribute &attr);
+	virtual bool is_AlarmFormula_allowed(Tango::AttReqType type);
+	void add_AlarmFormula_dynamic_attribute(string attname);
+	void remove_AlarmFormula_dynamic_attribute(string attname);
+	Tango::DevString *get_AlarmFormula_data_ptr(string &name);
+	map<string,Tango::DevString>	   AlarmFormula_data;
 
 	//--------------------------------------------------------
 	/**
diff --git a/src/Alarm.xmi b/src/Alarm.xmi
index 07e0ecb..8259fc3 100644
--- a/src/Alarm.xmi
+++ b/src/Alarm.xmi
@@ -1,7 +1,7 @@
 <?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="Alarm" pogoRevision="9.1">
-    <description description="Elettra alarm device server" title="Elettra alarm device server" sourcePath="/home/graziano/workspace/git/alarm/src" language="Cpp" filestogenerate="XMI   file,Code files,Protected Regions" license="GPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false">
+  <classes name="Alarm" pogoRevision="9.4">
+    <description description="Elettra alarm device server" title="Elettra alarm device server" sourcePath="/home/graziano/ws/alarm/src" language="Cpp" filestogenerate="XMI   file,Code files,Protected Regions" license="GPL" copyright="" hasMandatoryProperty="false" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="false">
       <inheritances classname="Device_4Impl" sourcePath=""/>
       <identification contact="at elettra.eu - graziano.scalamera" author="graziano.scalamera" emailDomain="elettra.eu" classFamily="SoftwareSystem" siteSpecific="" platform="Unix Like" bus="Not Applicable" manufacturer="" reference=""/>
     </description>
@@ -134,13 +134,28 @@
       <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
     </attributes>
     <dynamicAttributes name="AlarmState" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
-      <dataType xsi:type="pogoDsl:BooleanType"/>
+      <dataType xsi:type="pogoDsl:EnumType"/>
       <changeEvent fire="true" libCheckCriteria="true"/>
       <archiveEvent fire="true" libCheckCriteria="true"/>
       <dataReadyEvent fire="false" libCheckCriteria="true"/>
       <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
       <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+      <enumLabels>NORM</enumLabels>
+      <enumLabels>UNACK</enumLabels>
+      <enumLabels>ACKED</enumLabels>
+      <enumLabels>RTNUN</enumLabels>
+      <enumLabels>SHLVD</enumLabels>
+      <enumLabels>DSUPR</enumLabels>
+      <enumLabels>OOSRV</enumLabels>
     </dynamicAttributes>
-    <preferences docHome="./doc_html" makefileHome="/usr/local/tango-9.2.2/share/pogo/preferences"/>
+    <dynamicAttributes name="AlarmFormula" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="true">
+      <dataType xsi:type="pogoDsl:StringType"/>
+      <changeEvent fire="true" libCheckCriteria="false"/>
+      <archiveEvent fire="true" libCheckCriteria="false"/>
+      <dataReadyEvent fire="false" libCheckCriteria="true"/>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+      <properties description="" label="" unit="" standardUnit="" displayUnit="" format="" maxValue="" minValue="" maxAlarm="" minAlarm="" maxWarning="" minWarning="" deltaTime="" deltaValue=""/>
+    </dynamicAttributes>
+    <preferences docHome="./doc_html" makefileHome="/usr/local/tango-9.2.5a/share/pogo/preferences"/>
   </classes>
 </pogoDsl:PogoSystem>
diff --git a/src/AlarmClass.h b/src/AlarmClass.h
index e215eb1..0d1676b 100644
--- a/src/AlarmClass.h
+++ b/src/AlarmClass.h
@@ -80,12 +80,27 @@ class AlarmStateAttrib: public Tango::Attr
 {
 public:
 	AlarmStateAttrib(const string &att_name):Attr(att_name.c_str(), 
-			Tango::DEV_BOOLEAN, Tango::READ) {};
+			Tango::DEV_ENUM, Tango::READ) {};
 	~AlarmStateAttrib() {};
 	virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
 		{(static_cast<Alarm *>(dev))->read_AlarmState(att);}
 	virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
 		{return (static_cast<Alarm *>(dev))->is_AlarmState_allowed(ty);}
+	virtual bool same_type(const type_info &in_type) {return typeid(AlarmStateEnum) == in_type;}
+	virtual string get_enum_type() {return string("AlarmStateEnum");}
+};
+
+//	Attribute AlarmFormula class definition
+class AlarmFormulaAttrib: public Tango::Attr
+{
+public:
+	AlarmFormulaAttrib(const string &att_name):Attr(att_name.c_str(), 
+			Tango::DEV_STRING, Tango::READ) {};
+	~AlarmFormulaAttrib() {};
+	virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att)
+		{(static_cast<Alarm *>(dev))->read_AlarmFormula(att);}
+	virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty)
+		{return (static_cast<Alarm *>(dev))->is_AlarmFormula_allowed(ty);}
 };
 
 
diff --git a/src/AlarmDynAttrUtils.cpp b/src/AlarmDynAttrUtils.cpp
index 122abfe..4a9991b 100644
--- a/src/AlarmDynAttrUtils.cpp
+++ b/src/AlarmDynAttrUtils.cpp
@@ -42,9 +42,10 @@ static const char *RcsId = "$Id:  $";
 /*----- PROTECTED REGION END -----*/	//	Alarm::DynAttrUtils.cpp
 
 //================================================================
-//  Attributes managed is:
+//  Attributes managed are:
 //================================================================
-//  AlarmState  |  Tango::DevBoolean	Scalar
+//  AlarmState    |  Tango::DevEnum	Scalar
+//  AlarmFormula  |  Tango::DevString	Scalar
 //================================================================
 
 //	For compatibility reason, this file (AlarmDynAttrUtils)
@@ -94,13 +95,24 @@ void Alarm::add_AlarmState_dynamic_attribute(string attname)
 	DEBUG_STREAM << __func__<<": entering name="<<attname;
 	
 	/*----- PROTECTED REGION END -----*/	//	Alarm::att_AlarmState_dynamic_attribute
+	{
+		vector<string> labels;
+		labels.push_back("NORM");
+		labels.push_back("UNACK");
+		labels.push_back("ACKED");
+		labels.push_back("RTNUN");
+		labels.push_back("SHLVD");
+		labels.push_back("DSUPR");
+		labels.push_back("OOSRV");
+		alarmstate_prop.set_enum_labels(labels);
+	}
 	alarmstate->set_default_properties(alarmstate_prop);
 	//	Not Polled
 	alarmstate->set_disp_level(Tango::OPERATOR);
 	//	Not Memorized
 	alarmstate->set_change_event(true, true);
 	alarmstate->set_archive_event(true, true);
-	AlarmState_data.insert(make_pair(attname, false));
+	AlarmState_data.insert(make_pair(attname, 0));
 	add_attribute(alarmstate);
 }
 //--------------------------------------------------------
@@ -113,7 +125,7 @@ void Alarm::add_AlarmState_dynamic_attribute(string attname)
 void Alarm::remove_AlarmState_dynamic_attribute(string attname)
 {
 	remove_attribute(attname, true);
-	map<string,Tango::DevBoolean>::iterator ite;
+	map<string,Tango::DevEnum>::iterator ite;
     if ((ite=AlarmState_data.find(attname))!=AlarmState_data.end())
     {
     	/*----- PROTECTED REGION ID(Alarm::remove_AlarmState_dynamic_attribute) ENABLED START -----*/
@@ -122,6 +134,67 @@ void Alarm::remove_AlarmState_dynamic_attribute(string attname)
 		AlarmState_data.erase(ite);
 	}
 }
+//--------------------------------------------------------
+/**
+ *	Add a AlarmFormula dynamic attribute.
+ *
+ *  parameter attname: attribute name to be cretated and added.
+ */
+//--------------------------------------------------------
+void Alarm::add_AlarmFormula_dynamic_attribute(string attname)
+{
+	//	Attribute : AlarmFormula
+	AlarmFormulaAttrib	*alarmformula = new AlarmFormulaAttrib(attname);
+	Tango::UserDefaultAttrProp	alarmformula_prop;
+	//	description	not set for AlarmFormula
+	//	label	not set for AlarmFormula
+	//	unit	not set for AlarmFormula
+	//	standard_unit	not set for AlarmFormula
+	//	display_unit	not set for AlarmFormula
+	//	format	not set for AlarmFormula
+	//	max_value	not set for AlarmFormula
+	//	min_value	not set for AlarmFormula
+	//	max_alarm	not set for AlarmFormula
+	//	min_alarm	not set for AlarmFormula
+	//	max_warning	not set for AlarmFormula
+	//	min_warning	not set for AlarmFormula
+	//	delta_t	not set for AlarmFormula
+	//	delta_val	not set for AlarmFormula
+	
+	/*----- PROTECTED REGION ID(Alarm::att_AlarmFormula_dynamic_attribute) ENABLED START -----*/
+	DEBUG_STREAM << __func__<<": entering name="<<attname;
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::att_AlarmFormula_dynamic_attribute
+	alarmformula->set_default_properties(alarmformula_prop);
+	//	Not Polled
+	alarmformula->set_disp_level(Tango::OPERATOR);
+	//	Not Memorized
+	alarmformula->set_change_event(true, false);
+	alarmformula->set_archive_event(true, false);
+	char array[1];
+	array[0] = '\0';
+	AlarmFormula_data.insert(make_pair(attname, array));
+	add_attribute(alarmformula);
+}
+//--------------------------------------------------------
+/**
+ *	remove a AlarmFormula dynamic attribute.
+ *
+ *  parameter attname: attribute name to be removed.
+ */
+//--------------------------------------------------------
+void Alarm::remove_AlarmFormula_dynamic_attribute(string attname)
+{
+	remove_attribute(attname, true);
+	map<string,Tango::DevString>::iterator ite;
+    if ((ite=AlarmFormula_data.find(attname))!=AlarmFormula_data.end())
+    {
+    	/*----- PROTECTED REGION ID(Alarm::remove_AlarmFormula_dynamic_attribute) ENABLED START -----*/
+    	
+    	/*----- PROTECTED REGION END -----*/	//	Alarm::remove_AlarmFormula_dynamic_attribute
+		AlarmFormula_data.erase(ite);
+	}
+}
 
 
 //============================================================
@@ -134,9 +207,9 @@ void Alarm::remove_AlarmState_dynamic_attribute(string attname)
  *  parameter attname: the specified attribute name.
  */
 //--------------------------------------------------------
-Tango::DevBoolean *Alarm::get_AlarmState_data_ptr(string &name)
+Tango::DevEnum *Alarm::get_AlarmState_data_ptr(string &name)
 {
-	map<string,Tango::DevBoolean>::iterator ite;
+	map<string,Tango::DevEnum>::iterator ite;
     if ((ite=AlarmState_data.find(name))==AlarmState_data.end())
     {
 		TangoSys_OMemStream	tms;
@@ -148,6 +221,27 @@ Tango::DevBoolean *Alarm::get_AlarmState_data_ptr(string &name)
     }
 	return  &(ite->second);
 }
+//--------------------------------------------------------
+/**
+ *	Return a pointer on AlarmFormula data.
+ *
+ *  parameter attname: the specified attribute name.
+ */
+//--------------------------------------------------------
+Tango::DevString *Alarm::get_AlarmFormula_data_ptr(string &name)
+{
+	map<string,Tango::DevString>::iterator ite;
+    if ((ite=AlarmFormula_data.find(name))==AlarmFormula_data.end())
+    {
+		TangoSys_OMemStream	tms;
+		tms << "Dynamic attribute " << name << " has not been created";
+		Tango::Except::throw_exception(
+					(const char *)"ATTRIBUTE_NOT_FOUND",
+					tms.str().c_str(),
+					(const char *)"Alarm::get_AlarmFormula_data_ptr()");
+    }
+	return  &(ite->second);
+}
 
 
 //=============================================================
diff --git a/src/AlarmStateMachine.cpp b/src/AlarmStateMachine.cpp
index 558ee6f..b38f2ae 100644
--- a/src/AlarmStateMachine.cpp
+++ b/src/AlarmStateMachine.cpp
@@ -82,6 +82,22 @@ bool Alarm::is_AlarmState_allowed(TANGO_UNUSED(Tango::AttReqType type))
 	return true;
 }
 
+//--------------------------------------------------------
+/**
+ *	Method      : Alarm::is_AlarmFormula_allowed()
+ *	Description : Execution allowed for AlarmFormula attribute
+ */
+//--------------------------------------------------------
+bool Alarm::is_AlarmFormula_allowed(TANGO_UNUSED(Tango::AttReqType type))
+{
+
+	//	Not any excluded states for AlarmFormula attribute in read access.
+	/*----- PROTECTED REGION ID(Alarm::AlarmFormulaStateAllowed_READ) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	Alarm::AlarmFormulaStateAllowed_READ
+	return true;
+}
+
 
 //=================================================
 //		Commands Allowed Methods
diff --git a/src/alarm_table.h b/src/alarm_table.h
index e829767..0bdf7b0 100644
--- a/src/alarm_table.h
+++ b/src/alarm_table.h
@@ -258,7 +258,9 @@ class alarm_t {
 		string name,
 					 formula;
 		string attr_name;
-		Tango::DevBoolean *attr_value;
+		string attr_name_formula;
+		Tango::DevEnum *attr_value;
+		Tango::DevString *attr_value_formula;
 		int quality;
 		string ex_reason;
 		string ex_desc;
-- 
GitLab