From 50b29ba2959de6503b95acb9e6f473709fc20129 Mon Sep 17 00:00:00 2001
From: Giuseppe Carboni <giuseppecarboni89@live.com>
Date: Sat, 23 Mar 2024 15:43:02 +0000
Subject: [PATCH] Fix #855, added `setAttenuations` command

---
 CHANGELOG.md                                  |  3 +-
 .../ParserLibrary/include/SP_parser.i         |  2 +
 .../ParserLibrary/include/SP_typeConversion.h | 38 ++++++++++++-
 .../ParserLibrary/include/SP_types.h          | 32 -----------
 .../Scheduler/include/Core_Operations.h       | 15 ++++++
 Common/Servers/Scheduler/src/Core.cpp         |  1 +
 .../Servers/Scheduler/src/Core_Operations.i   | 54 +++++++++++++++++++
 7 files changed, 110 insertions(+), 35 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index f12d48bf9..57627b6a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -102,7 +102,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/
                  The syntax for the command is the following: `enable=X;Y` with X and Y representing the 2 feeds the user would like to use for the Nodding observation.
                  This command must be placed in the <schedule_name>.bck file in order to work properly.
     issue #619 - Active surface components are now capable of changing look-up tables on the fly via the `asSetLUT` command
-    issue #806   Added support for the C-band receiver at the SRT
+    issue #806 - Added support for the C-band receiver at the SRT
+    issue #855 - Added `setAttenuations` command
 
 ## Fixed
 ## Changed
diff --git a/Common/Libraries/ParserLibrary/include/SP_parser.i b/Common/Libraries/ParserLibrary/include/SP_parser.i
index cddaf919a..a720cd9c3 100644
--- a/Common/Libraries/ParserLibrary/include/SP_parser.i
+++ b/Common/Libraries/ParserLibrary/include/SP_parser.i
@@ -99,6 +99,8 @@ IRA::CString CParser<OBJ>::executeCommand(const IRA::CString& command,IRA::CStri
 			IRA::CString answer("");
 			if (outNumber>0) {
 				for(int j=0;j<outNumber;++j) {
+					if(outParams[j] == "")
+						continue;
 					answer+=outParams[j];
 					answer+=IRA::CString(m_answerDelimiter);
 				}
diff --git a/Common/Libraries/ParserLibrary/include/SP_typeConversion.h b/Common/Libraries/ParserLibrary/include/SP_typeConversion.h
index bddba983c..252358da4 100644
--- a/Common/Libraries/ParserLibrary/include/SP_typeConversion.h
+++ b/Common/Libraries/ParserLibrary/include/SP_typeConversion.h
@@ -24,6 +24,38 @@ enum _sp_symbols {
 #define _SP_MULTI_ARGUMENT_SEPARATOR ';'
 #define _SP_MULTI_ARGUMENT_COMPACT_SEP 'x'
 
+#define _SP_JOLLYCHARACTER '*'
+#define _SP_JOLLYCHARACTER_REPLACEMENT "-1"
+
+#define _SP_WILDCARD_CLASS(NAME,REPLACE) \
+class NAME { \
+public: \
+	static char *replace(const char *str) { \
+		if (str[0]==_SP_JOLLYCHARACTER) { \
+			char * out=new char[strlen(REPLACE)+1]; \
+			strcpy(out,REPLACE); \
+			return out; \
+		} \
+		else { \
+			char *tmp=new char[strlen(str)+1]; \
+			strcpy(tmp,str); \
+			return tmp; \
+		} \
+	} \
+}; \
+
+_SP_WILDCARD_CLASS(_default_wildcard,_SP_JOLLYCHARACTER_REPLACEMENT);
+
+class _no_wildcard
+{
+public:
+	static char *replace(const char *str) {
+		char *tmp=new char[strlen(str)+1];
+		strcpy(tmp,str);
+		return tmp;
+	}
+};
+
 class int_converter
 {
 public:
@@ -397,7 +429,7 @@ public:
 	}
 };
 
-class longSeq_converter
+class longSeq_converter : public _default_wildcard
 {
 public:
 	char *valToStr(const ACS::longSeq& val) {
@@ -439,6 +471,7 @@ public:
 			while (IRA::CIRATools::getNextToken(param,start,_SP_MULTI_ARGUMENT_SEPARATOR,ret)) {
 				errno=0;
 				token=const_cast<char *>((const char *)ret);
+				token=_default_wildcard::replace(token);
 				val=strtol(token,&endptr,10);
 				if ((errno==ERANGE && (val==LONG_MAX || val==LONG_MIN)) || (errno != 0 && val == 0)) {
 					_EXCPT(ParserErrors::BadTypeFormatExImpl,ex,"longSeq_converter::strToVal()");
@@ -459,7 +492,7 @@ public:
 	}
 };
 
-class doubleSeq_converter
+class doubleSeq_converter : public _default_wildcard
 {
 public:
 	char *valToStr(const ACS::doubleSeq& val) {
@@ -501,6 +534,7 @@ public:
 			while (IRA::CIRATools::getNextToken(param,start,_SP_MULTI_ARGUMENT_SEPARATOR,ret)) {
 				errno=0;
 				token=const_cast<char *>((const char *)ret);
+				token=_default_wildcard::replace(token);
 				val=strtod(token,&endptr);
 				if ((errno==ERANGE && (val==HUGE_VALF || val==HUGE_VALF)) || (errno != 0 && val == 0)) {
 					_EXCPT(ParserErrors::BadTypeFormatExImpl,ex,"doubleSeq_converter::strToVal()");
diff --git a/Common/Libraries/ParserLibrary/include/SP_types.h b/Common/Libraries/ParserLibrary/include/SP_types.h
index 9b7e5e35a..0268c1ea5 100644
--- a/Common/Libraries/ParserLibrary/include/SP_types.h
+++ b/Common/Libraries/ParserLibrary/include/SP_types.h
@@ -32,40 +32,8 @@ C11_IGNORE_WARNING_POP
 
 #include "SP_typeConversion.h"
 
-#define _SP_JOLLYCHARACTER '*'
-#define _SP_JOLLYCHARACTER_REPLACEMENT "-1"
-
 namespace SimpleParser {
 
-#define _SP_WILDCARD_CLASS(NAME,REPLACE) \
-class NAME { \
-public: \
-	static char *replace(const char *str) { \
-		if (str[0]==_SP_JOLLYCHARACTER) { \
-			char * out=new char[strlen(REPLACE)+1]; \
-			strcpy(out,REPLACE); \
-			return out; \
-		} \
-		else { \
-			char *tmp=new char[strlen(str)+1]; \
-			strcpy(tmp,str); \
-			return tmp; \
-		} \
-	} \
-}; \
-
-_SP_WILDCARD_CLASS(_default_wildcard,_SP_JOLLYCHARACTER_REPLACEMENT);
-
-class _no_wildcard
-{
-public:
-	static char *replace(const char *str) {
-		char *tmp=new char[strlen(str)+1];
-		strcpy(tmp,str);
-		return tmp;
-	}
-};
-
 /**
  * This is the base class for all types that are known to the parser. New types can be easily added, just providing the converter class.
  * The converter class just have to implement the proper methods, <i>strToVal()</i> and <i>valToStr()</i>.
diff --git a/Common/Servers/Scheduler/include/Core_Operations.h b/Common/Servers/Scheduler/include/Core_Operations.h
index 65d169927..222b956fe 100644
--- a/Common/Servers/Scheduler/include/Core_Operations.h
+++ b/Common/Servers/Scheduler/include/Core_Operations.h
@@ -260,4 +260,19 @@ void _startRecording(const long& subScanId,const ACS::TimeInterval& duration) th
  */
 void _terminateScan() throw (ComponentErrors::OperationErrorExImpl,ComponentErrors::CORBAProblemExImpl,ComponentErrors::UnexpectedExImpl,ComponentErrors::CouldntGetComponentExImpl);
 
+/**
+ * Sets all the sections attenuations with a single command
+ * @param attenuations an ACS::doubleSeq containing all the desired sections attenuations
+ * @param message a return message that will return a list of sections that the system was not able to configure
+ * @throw ComponentErrors::CouldntGetComponentExImpl when the default backend component was not reachable
+ * @throw ComponentErrors::CORBAProblemExImpl when something went wrong while trying to read the current sections from the default backend component
+ * @throw ParserErrors::NotEnoughParametersExImpl when the user specifies less attenuations values than the currently configured number of sections
+ * @throw ParserErrors::TooManyParametersExImpl when the user specifies more attenuations values than the currently configured number of sections
+ */
+void _setAttenuations(const ACS::longSeq& attenuations, IRA::CString& message) throw (
+		ComponentErrors::CouldntGetComponentExImpl,
+		ComponentErrors::CORBAProblemExImpl,
+		ParserErrors::NotEnoughParametersExImpl,
+		ParserErrors::TooManyParametersExImpl);
+
 #endif /* CORE_OPERATIONS_H_ */
diff --git a/Common/Servers/Scheduler/src/Core.cpp b/Common/Servers/Scheduler/src/Core.cpp
index 888b55ddc..34af8a4b5 100644
--- a/Common/Servers/Scheduler/src/Core.cpp
+++ b/Common/Servers/Scheduler/src/Core.cpp
@@ -158,6 +158,7 @@ void CCore::execute() throw(ComponentErrors::TimerErrorExImpl, ComponentErrors::
 	m_parser->add("startRecording", new function2<CCore, non_constant, void_type, I<long_type>, I<interval_type> >(this, &CCore::_startRecording), 2);
 	m_parser->add("terminateScan", new function0<CCore, non_constant, void_type>(this, &CCore::_terminateScan), 0);
 	m_parser->add("goOff", new function2<CCore, non_constant, void_type, I<enum_type<AntennaFrame2String, Antenna::TCoordinateFrame> >, I<double_type> >(this, &CCore::goOff), 2);
+	m_parser->add("setAttenuations", new function2<CCore, non_constant, void_type, I<longSeq_type>, O<longString_type> >(this, &CCore::_setAttenuations), 1);
 
 	//add remote commands ************  should be loaded from a CDB table............................**********/
 	// antenna subsystem
diff --git a/Common/Servers/Scheduler/src/Core_Operations.i b/Common/Servers/Scheduler/src/Core_Operations.i
index b693b3a1b..8b323f0ec 100644
--- a/Common/Servers/Scheduler/src/Core_Operations.i
+++ b/Common/Servers/Scheduler/src/Core_Operations.i
@@ -1175,3 +1175,57 @@ void CCore::_startSchedule(const char* scheduleFile,const char * startSubScan) t
 		m_schedExecuter->startSchedule(scheduleFile,startSubScan);
 	}
 }
+
+void CCore::_setAttenuations(const ACS::longSeq& attenuations, IRA::CString& message) throw (
+		ComponentErrors::CouldntGetComponentExImpl,
+		ComponentErrors::CORBAProblemExImpl,
+		ParserErrors::NotEnoughParametersExImpl,
+		ParserErrors::TooManyParametersExImpl)
+{
+	baci::ThreadSyncGuard guard(&m_mutex);
+	loadDefaultBackend(); // throw ComponentErrors::CouldntGetComponentExImpl& err)
+
+	ACS::longSeq inputSection;
+	ACSErr::Completion_var comp;
+	try
+	{
+		inputSection = *m_defaultBackend->inputSection()->get_sync(comp.out());
+	}
+	catch(CORBA::SystemException& ex)
+	{
+		_EXCPT(ComponentErrors::CORBAProblemExImpl, impl, "CCore::_setAttenuations()");
+		impl.setName(ex._name());
+		impl.setMinor(ex.minor());
+		throw impl;
+	}
+
+	if(attenuations.length() < inputSection.length())
+	{
+		_EXCPT(ParserErrors::NotEnoughParametersExImpl, impl, "CCore::_setAttenuations()");
+		throw impl;
+	}
+	else if(attenuations.length() > inputSection.length())
+	{
+		_EXCPT(ParserErrors::TooManyParametersExImpl, impl, "CCore::_setAttenuations()");
+		throw impl;
+	}
+
+	std::string error = "";
+
+	for(size_t i = 0; i < inputSection.length(); i++)
+	{
+		if(attenuations[i] != -1) // -1 means the user typed an asterisk for this section, keep the same attenuation
+		{
+			try
+			{
+				m_defaultBackend->setAttenuation(inputSection[i], attenuations[i]);
+			}
+			catch(...)
+			{
+				error += std::string(error.empty() ? "" : "\n") + "Could not set attenuation for section " + std::to_string(inputSection[i]);
+			}
+		}
+	}
+
+	error.empty() ? message.Format("") : message.Format("STR %s", error.c_str());
+}
-- 
GitLab