From 89beff282fc2321f70020e47b6a8a0745b7e0e2d Mon Sep 17 00:00:00 2001
From: gscalamera <graziano.scalamera@elettra.eu>
Date: Fri, 26 May 2017 11:35:27 +0200
Subject: [PATCH] Addode GetAlarmInfo command

---
 src/AlarmHandler.cpp             | 184 ++++++++++++++++++++++++++++++-
 src/AlarmHandler.h               |  16 +++
 src/AlarmHandler.xmi             |  18 +++
 src/AlarmHandlerClass.cpp        |  55 +++++++++
 src/AlarmHandlerClass.h          |  46 ++++++++
 src/AlarmHandlerStateMachine.cpp |  30 +++++
 src/alarm_grammar.h              |  12 ++
 src/alarm_table.h                |   1 +
 8 files changed, 359 insertions(+), 3 deletions(-)

diff --git a/src/AlarmHandler.cpp b/src/AlarmHandler.cpp
index d67173b..7b59334 100644
--- a/src/AlarmHandler.cpp
+++ b/src/AlarmHandler.cpp
@@ -106,6 +106,8 @@ static const char __FILE__rev[] = __FILE__ " $Revision: 1.29 $";
 //  Enable           |  enable
 //  Disable          |  disable
 //  ResetStatistics  |  reset_statistics
+//  StopNew          |  stop_new
+//  GetAlarmInfo     |  get_alarm_info
 //================================================================
 
 //================================================================
@@ -2857,6 +2859,182 @@ void AlarmHandler::reset_statistics()
 	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::reset_statistics
 }
 //--------------------------------------------------------
+/**
+ *	Command StopNew related method
+ *	Description: Stop audible indications on the GUI
+ *
+ */
+//--------------------------------------------------------
+void AlarmHandler::stop_new()
+{
+	DEBUG_STREAM << "AlarmHandler::StopNew()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(AlarmHandler::stop_new) ENABLED START -----*/
+	
+	//	Add your own code
+	//12-06-08: StopNew command set is_new to 0
+	//	Add your own code to control device here
+	alarm_container_t::iterator ai;
+	alarms.vlock->readerIn();
+	for (ai = alarms.v_alarm.begin(); ai != alarms.v_alarm.end(); ai++) {
+		ai->second.is_new = 0;		//set all alarm as no more new
+	}
+	alarms.vlock->readerOut();
+
+	prepare_alarm_attr();
+	try
+	{
+		if(ds_num == 0)
+		{
+			//attr.set_value_date_quality(ds,0/*gettime()*/,Tango::ATTR_WARNING, ds_num, 0, false);
+			struct timeval now;
+			gettimeofday(&now,NULL);
+			push_change_event("alarm",(char**)ds,now,Tango::ATTR_WARNING, ds_num, 0, false);
+		}
+		else
+		{
+			//attr.set_value(ds, ds_num, 0, false);
+			push_change_event("alarm",ds, ds_num, 0, false);
+		}
+		push_change_event("normalAlarms",&attr_normalAlarms_read[0], normalAlarms_sz);
+		push_change_event("unacknowledgedAlarms",&attr_unacknowledgedAlarms_read[0], unacknowledgedAlarms_sz);
+		push_change_event("acknowledgedAlarms",&attr_acknowledgedAlarms_read[0], acknowledgedAlarms_sz);
+		push_change_event("unacknowledgedNormalAlarms",&attr_unacknowledgedNormalAlarms_read[0], unacknowledgedNormalAlarms_sz);
+		push_change_event("shelvedAlarms",&attr_shelvedAlarms_read[0], shelvedAlarms_sz);
+		push_change_event("outOfServiceAlarms",&attr_outOfServiceAlarms_read[0], outOfServiceAlarms_sz);
+		push_change_event("silencedAlarms",&attr_silencedAlarms_read[0], silencedAlarms_sz);
+		push_change_event("listAlarms",&attr_listAlarms_read[0], listAlarms_sz);
+		push_change_event("frequencyAlarms",&attr_frequencyAlarms_read[0], listAlarms_sz);
+		push_change_event("audibleAlarm",attr_audibleAlarm_read);
+		push_archive_event("normalAlarms",&attr_normalAlarms_read[0], normalAlarms_sz);
+		push_archive_event("unacknowledgedAlarms",&attr_unacknowledgedAlarms_read[0], unacknowledgedAlarms_sz);
+		push_archive_event("acknowledgedAlarms",&attr_acknowledgedAlarms_read[0], acknowledgedAlarms_sz);
+		push_archive_event("unacknowledgedNormalAlarms",&attr_unacknowledgedNormalAlarms_read[0], unacknowledgedNormalAlarms_sz);
+		push_archive_event("shelvedAlarms",&attr_shelvedAlarms_read[0], shelvedAlarms_sz);
+		push_archive_event("outOfServiceAlarms",&attr_outOfServiceAlarms_read[0], outOfServiceAlarms_sz);
+		push_archive_event("silencedAlarms",&attr_silencedAlarms_read[0], silencedAlarms_sz);
+		push_archive_event("listAlarms",&attr_listAlarms_read[0], listAlarms_sz);
+		push_archive_event("frequencyAlarms",&attr_frequencyAlarms_read[0], listAlarms_sz);
+		push_archive_event("audibleAlarm",attr_audibleAlarm_read);
+	} catch(Tango::DevFailed& e)
+	{
+		ostringstream err;
+		err << "error pushing alarm change event err=" << e.errors[0].desc;
+		INFO_STREAM << __func__<<": " << err.str() << endl;
+	}
+
+	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::stop_new
+}
+//--------------------------------------------------------
+/**
+ *	Command GetAlarmInfo related method
+ *	Description: Returns the complete attribute info as an array of key=value
+ *
+ *	@param argin Alarm name
+ *	@returns Complete attribute info as an array of key=value
+ */
+//--------------------------------------------------------
+Tango::DevVarStringArray *AlarmHandler::get_alarm_info(Tango::DevString argin)
+{
+	Tango::DevVarStringArray *argout;
+	DEBUG_STREAM << "AlarmHandler::GetAlarmInfo()  - " << device_name << endl;
+	/*----- PROTECTED REGION ID(AlarmHandler::get_alarm_info) ENABLED START -----*/
+	
+	//	Add your own code
+	alarms.vlock->readerIn();
+
+	alarm_container_t::iterator it = alarms.v_alarm.find(argin);
+	vector<string> info;
+
+	if(it == alarms.v_alarm.end())
+	{
+		alarms.vlock->readerOut();
+       	ostringstream o;
+		o << "Alarm '" << argin << "' not found";
+       	DEBUG_STREAM <<__func__ << ": " << o.str() << endl;
+       	Tango::Except::throw_exception( \
+				(const char*)"NOT FOUND", \
+				(const char*)o.str().c_str(), \
+				(const char*)__func__, Tango::ERR);
+	}
+
+	info.push_back(KEY(NAME_KEY)+it->first);
+
+	Tango::MultiAttribute *m_attr = get_device_attr();
+	int attr_ind = m_attr->get_attr_ind_by_name(it->second.attr_name.c_str());
+	Tango::Attribute &attribute = m_attr->get_attr_by_ind(attr_ind);
+
+	ostringstream tmp_val;
+	vector<string> enum_labels = attribute.get_enum_labels();
+	if(*(it->second.attr_value) >= 0 && *(it->second.attr_value) < enum_labels.size())
+		tmp_val << enum_labels[*(it->second.attr_value)];
+	else
+		tmp_val << "UNKNOWN_ENUM(" << *(it->second.attr_value) << ")";
+
+	info.push_back(KEY(VALUE_KEY)+tmp_val.str());
+
+	info.push_back(KEY(FORMULA_KEY)+it->second.formula);
+	info.push_back(KEY(ATTR_VALUES_KEY)+it->second.attr_values);
+
+	ostringstream tmp_qual;
+	/*size_t siz = formula_grammar.attr_quality.size();
+	if((it->second.quality) >= 0 && (it->second.quality) < siz)
+		tmp_qual << formula_grammar.attr_quality[it->second.quality];
+	 */
+	tmp_qual << it->second.quality;
+	info.push_back(KEY(QUALITY_KEY)+tmp_qual.str());
+	ostringstream tmp_ex;
+	tmp_ex.str("");
+	if(it->second.ex_reason.length() > 0 || it->second.ex_desc.length() > 0 || it->second.ex_origin.length() > 0)
+		tmp_ex << "Reason: '" << it->second.ex_reason << "' Desc: '" << it->second.ex_desc << "' Origin: '" << it->second.ex_origin << "'";
+	info.push_back(KEY(EXCEPTION_KEY)+tmp_ex.str());
+	ostringstream tmp;
+	tmp.str("");
+	tmp << (it->second.enabled ? "true" : "false");
+	info.push_back(KEY(ENABLED_KEY)+tmp.str());	//TODO: redundant, information already in attr_value
+	tmp.str("");
+	tmp << (it->second.shelved ? "true" : "false");
+	info.push_back(KEY(SHELVED_KEY)+tmp.str());	//TODO: redundant, information already in attr_value
+	info.push_back(KEY(ACKNOWLEDGED_KEY)+it->second.ack);	//TODO: redundant, information already in attr_value
+	tmp.str("");
+	tmp << (it->second.is_new ? "true" : "false");
+	info.push_back(KEY(AUDIBLE_KEY)+tmp.str());
+	tmp.str("");
+	tmp << (it->second.on_counter);
+	info.push_back(KEY(ON_COUNTER_KEY)+tmp.str());
+	tmp.str("");
+	tmp << (it->second.off_counter);
+	info.push_back(KEY(OFF_COUNTER_KEY)+tmp.str());
+	tmp.str("");
+	tmp << (it->second.freq_counter);
+	info.push_back(KEY(FREQ_COUNTER_KEY)+tmp.str());
+
+	tmp.str("");
+	tmp << (it->second.on_delay);
+	info.push_back(KEY(ONDELAY_KEY)+tmp.str());
+	tmp.str("");
+	tmp << (it->second.on_delay);
+	info.push_back(KEY(OFFDELAY_KEY)+tmp.str());
+	info.push_back(KEY(LEVEL_KEY)+it->second.lev);
+	tmp.str("");
+	tmp << (it->second.silent_time);
+	info.push_back(KEY(SILENT_TIME_KEY)+tmp.str());
+	tmp.str("");
+	tmp << (it->second.silenced);
+	info.push_back(KEY(SILENT_TIME_REMAINING_KEY)+tmp.str());
+	info.push_back(KEY(GROUP_KEY)+it->second.grp2str());
+	info.push_back(KEY(MESSAGE_KEY)+it->second.msg);
+	info.push_back(KEY(ON_COMMAND_KEY)+it->second.cmd_name_a);
+	info.push_back(KEY(OFF_COMMAND_KEY)+it->second.cmd_name_n);
+
+	alarms.vlock->readerOut();
+	argout = new Tango::DevVarStringArray();
+	argout->length(info.size());
+	for(size_t i=0; i<info.size(); i++)
+		(*argout)[i] = Tango::string_dup(info[i].c_str());
+	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::get_alarm_info
+	return argout;
+}
+//--------------------------------------------------------
 /**
  *	Method      : AlarmHandler::add_dynamic_commands()
  *	Description : Create the dynamic commands if any
@@ -3451,10 +3629,10 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
 		it->second.freq_counter++;
 		string tmpname=it->first;
 		try {
-			string attr_values;
-			res = eval_formula(it->second.formula_tree, attr_values);
+			it->second.attr_values = string("");
+			res = eval_formula(it->second.formula_tree, it->second.attr_values);
 			DEBUG_STREAM << "AlarmHandler::"<<__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
+			changed = alarms.update(tmpname, ts, res, it->second.attr_values, it->second.grp2str(), it->second.msg, it->second.formula); 		//update internal structure and log to db
 			Tango::DevEnum *attr_value = get_AlarmState_data_ptr(it->second.attr_name);
 			if(!it->second.enabled)
 				*attr_value = _OOSRV;
diff --git a/src/AlarmHandler.h b/src/AlarmHandler.h
index d1c7870..ecb5fdf 100644
--- a/src/AlarmHandler.h
+++ b/src/AlarmHandler.h
@@ -450,6 +450,22 @@ public:
 	 */
 	virtual void reset_statistics();
 	virtual bool is_ResetStatistics_allowed(const CORBA::Any &any);
+	/**
+	 *	Command StopNew related method
+	 *	Description: Stop audible indications on the GUI
+	 *
+	 */
+	virtual void stop_new();
+	virtual bool is_StopNew_allowed(const CORBA::Any &any);
+	/**
+	 *	Command GetAlarmInfo related method
+	 *	Description: Returns the complete attribute info as an array of key=value
+	 *
+	 *	@param argin Alarm name
+	 *	@returns Complete attribute info as an array of key=value
+	 */
+	virtual Tango::DevVarStringArray *get_alarm_info(Tango::DevString argin);
+	virtual bool is_GetAlarmInfo_allowed(const CORBA::Any &any);
 
 
 	//--------------------------------------------------------
diff --git a/src/AlarmHandler.xmi b/src/AlarmHandler.xmi
index f43bb35..f5421bc 100644
--- a/src/AlarmHandler.xmi
+++ b/src/AlarmHandler.xmi
@@ -136,6 +136,24 @@
       </argout>
       <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
     </commands>
+    <commands name="StopNew" description="Stop audible indications on the GUI" execMethod="stop_new" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argin>
+      <argout description="">
+        <type xsi:type="pogoDsl:VoidType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
+    <commands name="GetAlarmInfo" description="Returns the complete attribute info as an array of key=value" execMethod="get_alarm_info" displayLevel="OPERATOR" polledPeriod="0" isDynamic="false">
+      <argin description="Alarm name">
+        <type xsi:type="pogoDsl:StringType"/>
+      </argin>
+      <argout description="Complete attribute info as an array of key=value">
+        <type xsi:type="pogoDsl:StringArrayType"/>
+      </argout>
+      <status abstract="false" inherited="false" concrete="true" concreteHere="true"/>
+    </commands>
     <attributes name="audibleAlarm" attType="Scalar" rwType="READ" displayLevel="OPERATOR" polledPeriod="0" maxX="" maxY="" allocReadMember="true" isDynamic="false">
       <dataType xsi:type="pogoDsl:BooleanType"/>
       <changeEvent fire="true" libCheckCriteria="false"/>
diff --git a/src/AlarmHandlerClass.cpp b/src/AlarmHandlerClass.cpp
index a2b7b70..03d4039 100644
--- a/src/AlarmHandlerClass.cpp
+++ b/src/AlarmHandlerClass.cpp
@@ -368,6 +368,43 @@ CORBA::Any *ResetStatisticsClass::execute(Tango::DeviceImpl *device, TANGO_UNUSE
 	return new CORBA::Any();
 }
 
+//--------------------------------------------------------
+/**
+ * method : 		StopNewClass::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 *StopNewClass::execute(Tango::DeviceImpl *device, TANGO_UNUSED(const CORBA::Any &in_any))
+{
+	cout2 << "StopNewClass::execute(): arrived" << endl;
+	((static_cast<AlarmHandler *>(device))->stop_new());
+	return new CORBA::Any();
+}
+
+//--------------------------------------------------------
+/**
+ * method : 		GetAlarmInfoClass::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 *GetAlarmInfoClass::execute(Tango::DeviceImpl *device, const CORBA::Any &in_any)
+{
+	cout2 << "GetAlarmInfoClass::execute(): arrived" << endl;
+	Tango::DevString argin;
+	extract(in_any, argin);
+	return insert((static_cast<AlarmHandler *>(device))->get_alarm_info(argin));
+}
+
 
 //===================================================================
 //	Properties management
@@ -1036,6 +1073,24 @@ void AlarmHandlerClass::command_factory()
 			Tango::OPERATOR);
 	command_list.push_back(pResetStatisticsCmd);
 
+	//	Command StopNew
+	StopNewClass	*pStopNewCmd =
+		new StopNewClass("StopNew",
+			Tango::DEV_VOID, Tango::DEV_VOID,
+			"",
+			"",
+			Tango::OPERATOR);
+	command_list.push_back(pStopNewCmd);
+
+	//	Command GetAlarmInfo
+	GetAlarmInfoClass	*pGetAlarmInfoCmd =
+		new GetAlarmInfoClass("GetAlarmInfo",
+			Tango::DEV_STRING, Tango::DEVVAR_STRINGARRAY,
+			"Alarm name",
+			"Complete attribute info as an array of key=value",
+			Tango::OPERATOR);
+	command_list.push_back(pGetAlarmInfoCmd);
+
 	/*----- PROTECTED REGION ID(AlarmHandlerClass::command_factory_after) ENABLED START -----*/
 	
 	//	Add your own code
diff --git a/src/AlarmHandlerClass.h b/src/AlarmHandlerClass.h
index 9ba831c..039ecb8 100644
--- a/src/AlarmHandlerClass.h
+++ b/src/AlarmHandlerClass.h
@@ -499,6 +499,52 @@ public:
 	{return (static_cast<AlarmHandler *>(dev))->is_ResetStatistics_allowed(any);}
 };
 
+//	Command StopNew class definition
+class StopNewClass : public Tango::Command
+{
+public:
+	StopNewClass(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)	{};
+
+	StopNewClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~StopNewClass() {};
+	
+	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<AlarmHandler *>(dev))->is_StopNew_allowed(any);}
+};
+
+//	Command GetAlarmInfo class definition
+class GetAlarmInfoClass : public Tango::Command
+{
+public:
+	GetAlarmInfoClass(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)	{};
+
+	GetAlarmInfoClass(const char   *name,
+	               Tango::CmdArgType in,
+				   Tango::CmdArgType out)
+	:Command(name,in,out)	{};
+	~GetAlarmInfoClass() {};
+	
+	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<AlarmHandler *>(dev))->is_GetAlarmInfo_allowed(any);}
+};
+
 
 /**
  *	The AlarmHandlerClass singleton definition
diff --git a/src/AlarmHandlerStateMachine.cpp b/src/AlarmHandlerStateMachine.cpp
index 8fc1514..92d97f9 100644
--- a/src/AlarmHandlerStateMachine.cpp
+++ b/src/AlarmHandlerStateMachine.cpp
@@ -438,6 +438,36 @@ bool AlarmHandler::is_ResetStatistics_allowed(TANGO_UNUSED(const CORBA::Any &any
 	return true;
 }
 
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmHandler::is_StopNew_allowed()
+ *	Description : Execution allowed for StopNew attribute
+ */
+//--------------------------------------------------------
+bool AlarmHandler::is_StopNew_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for StopNew command.
+	/*----- PROTECTED REGION ID(AlarmHandler::StopNewStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::StopNewStateAllowed
+	return true;
+}
+
+//--------------------------------------------------------
+/**
+ *	Method      : AlarmHandler::is_GetAlarmInfo_allowed()
+ *	Description : Execution allowed for GetAlarmInfo attribute
+ */
+//--------------------------------------------------------
+bool AlarmHandler::is_GetAlarmInfo_allowed(TANGO_UNUSED(const CORBA::Any &any))
+{
+	//	Not any excluded states for GetAlarmInfo command.
+	/*----- PROTECTED REGION ID(AlarmHandler::GetAlarmInfoStateAllowed) ENABLED START -----*/
+	
+	/*----- PROTECTED REGION END -----*/	//	AlarmHandler::GetAlarmInfoStateAllowed
+	return true;
+}
+
 
 /*----- PROTECTED REGION ID(AlarmHandler::AlarmHandlerStateAllowed.AdditionalMethods) ENABLED START -----*/
 
diff --git a/src/alarm_grammar.h b/src/alarm_grammar.h
index fb2f743..1c5e8e5 100644
--- a/src/alarm_grammar.h
+++ b/src/alarm_grammar.h
@@ -78,6 +78,18 @@
 #define ON_COMMAND_KEY		"on_command"
 #define OFF_COMMAND_KEY		"off_command"
 #define ENABLED_KEY			"enabled"
+
+#define SILENT_TIME_REMAINING_KEY		"silent_time_remaining"
+#define SHELVED_KEY			"shelved"
+#define ACKNOWLEDGED_KEY	"ack"
+#define ATTR_VALUES_KEY		"attr_values"
+#define VALUE_KEY			"value"
+#define ON_COUNTER_KEY		"on_counter"
+#define OFF_COUNTER_KEY		"off_counter"
+#define QUALITY_KEY			"quality"
+#define EXCEPTION_KEY		"exception"
+#define AUDIBLE_KEY			"audible"
+#define FREQ_COUNTER_KEY	"freq_counter"
 #define KEY(S_VAL)  		S_VAL "="
 
 #define SEP					";"
diff --git a/src/alarm_table.h b/src/alarm_table.h
index 1780f77..0a33962 100644
--- a/src/alarm_table.h
+++ b/src/alarm_table.h
@@ -293,6 +293,7 @@ class alarm_t {
 		Tango::TimeVal ts_time_silenced;	//says when it has been silenced
 		int silent_time;			//minutes max to be silent
 		int silenced;				//minutes still to be silent
+		string attr_values;		//attr_values
 		string attr_values_delay;	//attr_values of first occurrence of alarm waiting for on or off delay
 		string cmd_name_a;					//action to execute: when NORMAL -> ALARM, cmd_name = cmd_dp_a/cmd_action_a
 		string cmd_dp_a;						//device proxy part of cmd_name_a
-- 
GitLab