Send_Param for RTAI-XML

Stienen, A.H.A. (CTW) a.h.a.stienen at utwente.nl
Tue Jul 4 22:49:37 CEST 2006


Hi all,

I'm now trying to adapt the testsuite programs of RTAI-XML to be able to 
update a single parameter of a running Simulink model via the command 
line. In the testsuite, there are several programs, f.i. to connect to a 
running model and start or stop it.

I made two additions: get_param.c and send_param.c (named after the 
similar classes in rtaixml.cpp). I copied both get_param.c, send_param.c 
and rtaixml.cpp below this message. The first one workes and outputs all 
the parameters in a simple model I made. As an example output of get_param:

aruser at AR2:/usr/src/rtai-xml-0.4.1/testsuite$ ./get_param
{[state:6,str:Parameters 
ok.],{xmltest/Gain,Gain,1,1,{1}},{xmltest/Constant,Value,1,1,{1}},{xmltest/Bias,Bias,1,1,{0}},{xmltest/Comedi 
Analog In,P1,1,1,{2}},{xmltest/Comedi Analog 
In,P2,1,1,{0}},{xmltest/Comedi Analog In,P3,1,1,{0}},{xmltest/Comedi 
Analog In,P4,1,1,{1}},{xmltest/Comedi Analog 
In,P5,1,1,{0.1}},{xmltest/RTAI-Lab Scope,P1,1,1,{2}},{xmltest/RTAI-Lab 
Scope,P2,1,1,{-1}}}

But when I run send_param, I get this error message:

aruser at AR2:/usr/src/rtai-xml-0.4.1/testsuite$ ./send_param
[state:1,str:Error in updating parameters.]

Reading rtaixml.cpp leads me to think that I can't update a single block 
like I've done now in send_param.c, but have to insert the parameters 
for all the blocks, even the ones I don't want to update. The class 
description of send_param in rtaixml.cpp seems to say so, but I'm not 
sure...

Any ideas?

Kind regards,
Arno.



//**********************
//get_param.c
//**********************

#include "XmlRpc.h"
#include "../socket/Socket.h"
#include "../socket/SocketException.h"
#include <iostream>
#include <unistd.h>

using namespace XmlRpc;

int main(int argc, char* argv[])
{

   int port_xml=8080;
   std::string server="localhost";
   std::string from_server;

   XmlRpcClient c(server.c_str(), port_xml);
   XmlRpcValue noArgs, result;

   noArgs[0]="IFTASK";
   if (c.execute("Get_Param", noArgs, result))
     std::cout << result << "\n";
   else {
     std::cout << "Error calling 'Get_Param'\n\n";
     exit(1);
   }
   return 0;
}

//**********************
//send_param.c
//**********************

#include "XmlRpc.h"
#include "../socket/Socket.h"
#include "../socket/SocketException.h"
#include <iostream>
#include <unistd.h>

using namespace XmlRpc;

int main(int argc, char* argv[])
{

   int port_xml=8080;
   std::string server="localhost";
   std::string from_server;

   XmlRpcClient c(server.c_str(), port_xml);
   XmlRpcValue noArgs, result;

   noArgs[5]="3";
   noArgs[4]="1";
   noArgs[3]="1";
   noArgs[2]="Gain";
   noArgs[1]="xmltest/Gain";
   noArgs[0]="IFTASK";
   if (c.execute("Send_Param", noArgs, result))
     std::cout << result << "\n";
   else {
     std::cout << "Error calling 'Send_Param'\n\n";
     exit(1);
   }
   return 0;
}

//**********************
//rtaixml.cpp
//**********************

/** \file rtaixml.cpp
*COPYRIGHT (C) 2004  Michele Basso   (basso at dsi.unifi.it)
*                    Marco Romagnoli (romagnoli at control.dsi.unifi.it)
*                    Massimo Vassalli(vassalli at inoa.it)
*
*This library 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 2 of the License, or (at your option) any later version.
*
*This library 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 this library; if not, write to the Free Software
*Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
**/



#include "socket/ServerSocket.h"
#include "socket/SocketException.h"
#include "XmlRpc.h"

using namespace XmlRpc;

#include <Params_Manager.h>
#include <Signal_Manager.h>

#include <string>
#include <sstream>

#include <semaphore.h>

#include <iostream>
#include <stdio.h>
#include <pthread.h>
#include <sys/poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/io.h>
#include <sys/poll.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#include <rtai_netrpc.h>
#include <rtai_msg.h>
#include <rtai_mbx.h>

#include <rtaixml.h>

XmlRpcServer s;
int portXML = 8080;

int portSocket=30000;
bool client_connected=false;
bool client_waiting=false;

sem_t mutex;
sem_t mutex_sock;
ServerSocket listen_sock;
ServerSocket sending_sock;

static RT_TASK *Target_Interface_Task;
static RT_TASK *RLG_Main_Task;
static pthread_t Target_Interface_Thread;
static pthread_t *Get_Scope_Data_Thread;
static pthread_t Send_Data_Target_Thread;

static int Verbose = 0;

static int Is_Target_Connected;
static unsigned int Is_Target_Running;
static int End_App;
static int End_All;
static long Target_Node;
static long RPC_port=0;

int Num_Tunable_Parameters;
int Num_Tunable_Blocks;
int Num_Scopes;

Target_Parameters_T *Tunable_Parameters;
Target_Blocks_T *Tunable_Blocks;
Target_Scopes_T *Scopes;
Target_Logs_T *Logs;
Target_Leds_T *Leds;
Target_Meters_T *Meters;
Target_Synchs_T *Synchs;

Batch_Parameters_T Batch_Parameters[MAX_BATCH_PARAMS];
Preferences_T Preferences;
Profile_T *Profile;

Params_Manager *Parameters_Manager;
Signal_Manager *Signals_Manager;

const char *RLG_Target_Name;

static std::string ServerName("RLGM2");
static std::string TargetName("IFTASK");
static std::string ScopeMbxName("RTS");
static std::string target_directory("./");

bool script_execution=false;

static volatile int GlobalRet[16];

/** \brief It allows you to send a message to the specified task
  *
  * This function let you  to send a message msg (unsigned int) to the task
  * specified. It is used to send a message to the target interface thread.
  * @param task the name of the task you want to communicate with.
  * @param msg message sent to the task. It's an unsigned int.
  * @param reply unused.
  */
static inline void RT_RPC(RT_TASK *task, unsigned int msg, unsigned int 
*reply)
{
     GlobalRet[msg & 0xf] = 0;
     rt_send(task, msg);
     while (!GlobalRet[msg & 0xf]) {
         msleep(100);            //to force a behavior similar to 
Fl::wait(time);
     }
}


static inline void RT_RETURN(RT_TASK *task, unsigned int reply)
{
     GlobalRet[reply] = 1;
}

/** \brief Obtain an unique id from a name.
  *
  * This function let you to obtain an unique id from a name. It gets 
the name and
  * attached to it an integer and then try to register this name inside the
  * RTAI domain.
  * @param root the name used to get the unique id
  * @return the unique RTAI id in case of success, elsewhere 0.
  *
  */
unsigned long get_an_id(const char *root)
{
     int i;
     char name[7];
     for (i = 0; i < MAX_NHOSTS; i++) {
         sprintf(name, "%s%d", root, i);
         if (!rt_get_adr(nam2num(name))) {
             return nam2num(name);
         }
     }
     return 0;
}

/** \brief It checks the existence if a target.
  *
  * 	This function let you know if a target with the specified name 
exists. It
  * check if the corresponding name is registered in the RTAI domain.
  * @param target_name the name of the target or any RTAI name you want 
to check
  * @return true if the name is registered elsewhere false.
  */

bool Is_There_A_Target(const std::string target_name)
{
	std::string testIP("127.0.0.1");
	if(std::string(Preferences.Target_IP)==testIP)
	{
		if (RT_get_adr(0,0,target_name.c_str()))
			return true;
		return false;
	}
	return true;
}


/** \class tConnect
  * \brief It allows you to connect the server to the target via XMLRPC.
  *
  * This method is available as web service. It allows you to establish 
a connection
  * between the specified target and the server. This operation is 
necessary before
  * doing any other action onthe target.
  * @param params it has to contain as element 0 the task name to 
connect and
  * (optional) as element 1 the name of the corresponding mailbox that 
the server uses
  * to communicate with the target. The real name of the mailbox is 
obtained by
  * calling the function get_an_id, that add at the end of the name a 
progressive
  * integer that it is used to distinguish mailboxes of different signals
  * @param result This variable contains the result of the execution of 
this
  * function. It contains three values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running. The last "port" contains the port 
number you
  * have to communicate with to obtain the signals.
  *
  * @return see parameter result.
  */
class tConnect : public XmlRpcServerMethod
{
public:
   tConnect(XmlRpcServer* s) : XmlRpcServerMethod("tConnect", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
     pid_t childpid;
     std::string temp;
   	if(!params.valid() || params.size()<1 || params.size()>2) {
         status["str"]="Number of parameters in calling CONNECT incorrect";
         status["state"]=(int)1;
	    status["port"]=(int)0;
	    result=status;
	    return;
     }
	if(script_execution && !Is_There_A_Target(std::string(params[0]))) {
	    childpid = fork();
	    if (childpid >= 0)
	    {
	        if (childpid == 0)
	        {
				listen_sock.Close();
				s.shutdown();
	            printf("Executing 'rtarget' script...\n");
	            execl("./rtarget","rtarget",std::string(params[0]).c_str(),0);
	            printf("...done.\n");
	            exit(0);
	        }
	        else
	        {
	            wait(NULL);
	            sleep(2);
	        }
	    }
	    else
	    {
	        perror("fork");
	        exit(0);
	    }
     }
	if(!Is_There_A_Target(std::string(params[0]))) {
         status["str"]="No "+std::string(params[0])+" target or bad 
interface task identifier";
         status["state"]=(int)0;
	    status["port"]=(int)0;
	    result=status;
	    return;
     }
     if(Is_Target_Connected)
	    RT_RPC(Target_Interface_Task, DISCONNECT_FROM_TARGET, 0);
	TargetName=std::string(params[0]);
	if(params.size()>1) {
		if(Verbose)
			std::cout<<"Connect: "<<params[1]<<"\t Valore 
corretto->"<<ScopeMbxName<<"\n";
		if(!Is_There_A_Target(std::string(params[1])+"0")) {
	        status["str"]="No "+std::string(params[1])+" mbx target";
	        status["state"]=(int)0;
		    status["port"]=(int)0;
		    result=status;
		    return;
	    }
		ScopeMbxName=std::string(params[1]);
	}
     if(!Is_Target_Connected)
	    RT_RPC(Target_Interface_Task, CONNECT_TO_TARGET, 0);
	else {
         status["str"]="Error.";
         status["state"]=(int)1;
	    status["port"]=(int)0;
	    result=status;
	    return;
     }
		
     status["str"] = Tunable_Parameters[0].model_name;
     //state are 4 bit.
     // Is_Target_Running | Is_Target_Connected | Target_Exist | Error
     status["state"] = 
(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
     status["port"]=(int)portSocket;
     if((int)Is_Target_Running==1){
		if (Verbose)
         	printf("\nResetting scopes\n");
		Signals_Manager->ResetAll();
     }
     if(!Is_Target_Connected) {
         status["str"]="Error.";
	    status["state"] = (int)1;
	    status["port"]=(int)0;
     }
     result = status;
    }

   std::string help() { return std::string("Allows Target connection"); }

} tconnect(&s);

/** \class Disconnect
  * \brief It allows you to disconnect the server from the target via 
XMLRPC.
  *
  * This method is available as web service. It allows you to interrupt 
a connection
  * with the specified target.
  * @param params it has to contain as element 0 the task name to disconnect
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */
class Disconnect : public XmlRpcServerMethod
{
public:
   Disconnect(XmlRpcServer* s) : XmlRpcServerMethod("Disconnect", s) {}
   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling DISCONNECT 
incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }
     if (Is_Target_Connected) {
	    RT_RPC(Target_Interface_Task, DISCONNECT_FROM_TARGET, 0);
         status["str"]="Disconnected from Target.";
         status["state"]=(int)2;
	    result=status;
     }
     else {
         status["str"]="Target not Connected";
         status["state"]=(int)0;
	    result=status;
     }
   }

   std::string help() { return std::string("Allows Target disconnection"); }

} disconnect(&s);


/** \class Info
  * \brief It allows you to get infos about the server and the target 
via XMLRPC.
  *
  * This method is available as web service. It allows you to get 
information
  * about the server and the target.
  * @param params it has to contain as element 0 the task name to get 
infos about
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running. The last "port" contains the port 
number you
  * have to communicate with to obtain the signals.
  *
  * @return see parameter result.
  */
class Info : public XmlRpcServerMethod
{
public:
   Info(XmlRpcServer* s) : XmlRpcServerMethod("Info", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
     std::string temp;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling INFO incorrect";
         status["state"]=(int)1;
	    status["port"]=(int)0;
	    result=status;
	    return;
     }
     if(!Is_Target_Connected){
         status["str"]="Target not connected";
	    status["state"] = (int)0;
	    status["port"]=(int)portSocket;
	    result=status;
	    return;
     }
     status["str"] = Tunable_Parameters[0].model_name;
     status["state"] = 
(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
     status["port"]=(int)portSocket;
     result = status;
    }

   std::string help() { return std::string("Get info about target."); }

} info(&s);    // This constructor registers the method with the server


/** \class Start
  * \brief It allows you to start the specified target via XMLRPC.
  *
  * This method is available as web service. It allows you to start a 
connected
  * target. If the specified target is not connected to the server, this 
function
  * return an error.
  * @param params it has to contain as element 0 the task name to start
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */
  class Start : public XmlRpcServerMethod
{
public:
   Start(XmlRpcServer* s) : XmlRpcServerMethod("Start", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling START incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }
     if(Is_Target_Connected)
         if (!Is_Target_Running){
	        RT_RPC(Target_Interface_Task, START_TARGET, 0);
	        status["str"]="Start Realtime Code";
         }
         else
	        status["str"]="Target already running";
     else
         status["str"]="Target not connected";
     status["state"] = 
(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
     result=status;
   }

   std::string help() { return std::string("Allows Target start"); }

} start(&s);    // This constructor registers the method with the server


/** \class Stop
  * \brief It allows you to stop the specified target via XMLRPC.
  *
  * This method is available as web service. It allows you to stop a 
connected
  * and running target. If the specified target is not connected to the
  * server, this function return an error.
  * @param params it has to contain as element 0 the task name to start
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */
class Stop : public XmlRpcServerMethod
{
public:
   Stop(XmlRpcServer* s) : XmlRpcServerMethod("Stop", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling STOP incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }
     if(Is_Target_Connected)
         if (Is_Target_Running){
	        RT_RPC(Target_Interface_Task, STOP_TARGET, 0);
	        status["str"]="Stop Realtime Code";
         }
         else
	        status["str"]="Target not running";
     else
         status["str"]="Target not connected";
     status["state"] = 
(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
     result=status;
   }

   std::string help() { return std::string("Allows Target stop"); }

} stop(&s);    // This constructor registers the method with the server


/** \class Stop_Server
  * \brief It allows you to stop the RTAI-XML Server via XMLRPC.
  *
  * This method is available as web service. It allows you to stop the 
server.
  *
  * @param params it has to contain as element 0 the server name. When
  * executing the RTAI-XML server is possible to provide a name for the 
server.
  * This name is used to register the soft real time thread that provide 
the
  * external interface in the RTAI domain. In order to stop the server 
you have
  * to know its name, in this way a little of security is provided.
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */
  class Stop_Server : public XmlRpcServerMethod
{
public:
   Stop_Server(XmlRpcServer* s) : XmlRpcServerMethod("Stop_Server", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling STOP_SERVER 
incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(ServerName)) {
         status["str"]="Servername incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	listen_sock.Close();
     s.shutdown();	//Stop of the XMLRPC Server
     rlg_quit_cb();
     rt_task_delete(RLG_Main_Task);
     status["str"]="Server stopped.";
     status["state"]=(int)0;
     result=status;
   }

   std::string help() { return std::string("Allows Server stop"); }

} stop_server(&s);    // This constructor registers the method with the 
server


/** \class Get_Param
  * \brief It allows you to get the parameters of the specified target 
via XMLRPC.
  *
  * This method is available as web service. It allows you to get the 
parameters
  * of a connected target. If the specified target is not connected to the
  * server, this function return an error.
  * @param params it has to contain as element 0 the task name.
  * @param result This variable contains the result of the execution of 
this
  * function. It is a vector of XmlRpcValue element of size number of 
parameters
  * +1. The first element contains two values. The first "str" is an 
human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running. The remaining elements contain the 
parameters. Each
  * element contains a parameters. Each parameter is an XmlRpcValue 
formed by
  * 4+parameter dimension elements.The first is the block name, the 
second is the
  * parameter name, the third is the number of rows the fourth is the 
number of
  * columns, the last (number of rows * number of column) values contain 
the
  * numerical values of the parameters.
  * If an error occurred only a one value vector is returned with the first
  * specified element.
  *
  * @return see parameter result.
  */
  class Get_Param : public XmlRpcServerMethod
{
public:
   Get_Param(XmlRpcServer* s) : XmlRpcServerMethod("Get_Param", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling GET_PARAMS 
incorrect";
         status["state"]=(int)1;
	    result[0]=status;
	    return;
     }
     if(!Is_Target_Connected){
         status["str"]="Target not connected";
	    status["state"] = (int)0;
	    result[0]=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result[0]=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result[0]=status;
	    return;
     }
     XmlRpcValue Param_XML;
     XmlRpcValue struct1;
     RT_RPC(Target_Interface_Task, GET_PARAMS, 0);
     Param_XML.setSize(Num_Tunable_Parameters+1);
     status["str"]="Parameters ok.";
     status["state"]=(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
     Param_XML[0]=status;
     struct1.setSize(5);
     for (int n = 0; n < Num_Tunable_Parameters; n++) {
         struct1[0] = Tunable_Parameters[n].block_name;
         struct1[1] = Tunable_Parameters[n].param_name;
         struct1[2] =  (int)Tunable_Parameters[n].n_rows;
         struct1[3] =  (int)Tunable_Parameters[n].n_cols;
         XmlRpcValue struct2;
 
struct2.setSize((int)(Tunable_Parameters[n].n_rows*Tunable_Parameters[n].n_cols));
         for (unsigned int nr = 0; nr < Tunable_Parameters[n].n_rows; 
nr++) {
             for (unsigned int nc = 0; nc < 
Tunable_Parameters[n].n_cols; nc++) {
                 struct2[nr*Tunable_Parameters[n].n_cols+nc] = 
Tunable_Parameters[n].data_value[nr*Tunable_Parameters[n].n_cols+nc];
             }
         }
         struct1[5] = struct2;
         Param_XML[n+1]=struct1;
     }
     result = Param_XML;
   }

   std::string help() { return std::string("Get Target parameters"); }

} get_param(&s);    // This constructor registers the method with the server


/** \class Send_Param
  * \brief It allows you to update new parameters on the specified 
target via XMLRPC.
  *
  * This method is available as web service. It allows you to update new 
parameters
  * on a connected target. If the specified target is not connected to the
  * server, this function return an error.
  * @param params it has to contain vector, the first element has to be 
the task name.
  * The remaining elements contain all the parameters of the target. So 
you have
  * to provided all the parameters not only the modified one. Each
  * element contains a parameters. Each parameter is an XmlRpcValue 
formed by
  * 4+parameter dimension elements.The first is the block name, the 
second is the
  * parameter name, the third is the number of rows the fourth is the 
number of
  * columns, the last (number of rows * number of column) values contain 
the
  * numerical values of the parameters.
  * @param result This variable contains the result of the execution of 
this
  * function. It is a vector of XmlRpcValue element of size number of 
parameters
  * +1. The first element contains two values. The first "str" is an 
human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */
class Send_Param : public XmlRpcServerMethod
{
public:
   Send_Param(XmlRpcServer* s) : XmlRpcServerMethod("Send_Param", s) {}

   //Il primo elemento di param e' IFTASK dopo vengono i parametri.
   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()==0) {
         status["str"]="Number of parameters in calling SEND_PARAMS 
incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(!Is_Target_Connected){
         status["str"]="Target not connected";
	    status["state"] = (int)0;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }
     int n_rows = 0;
     int n_cols = 0;
     int map_offset=0;
     if (Verbose) {
         printf("number of elements in params: %d\n",params.size()-1);
     }
     try{
	    for(int i=0; i < params.size()-1;i++){
		    XmlRpcValue temp,temp_value;
	        temp=params[i+1];
	        n_rows = (int)temp[2];
	        n_cols = (int)temp[3];
	        temp_value=temp[4];
	        for(int k=0; k<n_rows*n_cols;k++){
	            char temptune[6];
	            char tempjava[6];
	            sprintf(temptune,"%1.3e",Tunable_Parameters[i].data_value[k]);
	            sprintf(tempjava,"%1.3e",(double)temp_value[k]);
	            if (Verbose) {
	                printf("value :%s\n",tempjava);
	                printf("tuneb :%s\n",temptune);
	            }
	            if(strcmp(temptune,tempjava)!=0){
	                Tunable_Parameters[i].data_value[k]=(double)temp_value[k];
	                rlg_update_parameters_cb( k, 
map_offset,(double)temp_value[k]);
	            }
	        }
             map_offset++;   //this counter selects the parameter index 
to modify in the Target;
     	}
     } catch(XmlRpcException e){
         status["str"]="Error in updating parameters.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     status["str"]="Parameters on target updated.";
     status["state"]=(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
     result=status;
}

   std::string help() { return std::string("Upload Client parameter 
vector"); }

} send_param(&s);    // This constructor registers the method with the 
server

/** \class Get_Signal_Structure
  * \brief It allows you to get the structure of all the signals of the 
specified
  * target via XMLRPC.
  *
  * This method is available as web service. It allows you to get the 
structure
  * of all the signals of the connected target. If the specified target 
is not
  * connected to the server, this function return an error.
  * @param params it has to contain as element 0 the task name.
  * @param result This variable contains the result of the execution of 
this
  * function. It is a vector of XmlRpcValue element of size number of 
parameters
  * +1. The first element contains two values. The first "str" is an 
human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running. The remaining elements contain the signals
  * structure. Each element contains the structure of a signal. Each 
signal structure
  * is an XmlRpcValue formed by 3 dimension element.The first "str" is the
  * signal name, the second is the number of traces, the third is the 
sample time.
  * If an error occurred only a one value vector is returned with the first
  * specified element.
  *
  * @return see parameter result.
  */
class Get_Signal_Structure : public XmlRpcServerMethod
{
public:
   Get_Signal_Structure(XmlRpcServer* s) : 
XmlRpcServerMethod("Get_Signal_Structure", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
     XmlRpcValue Param_XML;
     XmlRpcValue struct1;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling 
GET_SIGNAL_STRUCTURE incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(!Is_Target_Connected){
         status["str"]="Target not connected";
	    status["state"] = (int)0;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }
     status["str"]="Signals structure ok.";
     status["state"]=(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
     Param_XML[0]=status;
     for (int n = 0; n < Num_Scopes; n++) {
         struct1["str"] = Scopes[n].name;
         struct1["i4"] = Scopes[n].ntraces;
         struct1["d"] = Scopes[n].dt;
         Param_XML[n+1]=struct1;
     }
     result = Param_XML;
   }

   std::string help() { return std::string("Get signal structure from 
Target"); }

} get_signal_structure(&s);    // This constructor registers the method 
with the server

/** \class Start_Data
  * \brief It allows you to enable the specified signal to send its data 
over the net.
  *
  * This method is available as web service. It allows you to enable a 
signal
  * to send the data over the net using the open socket with the specified
  * decimation.
  * @param params it has to contain two or three elements. The first is 
the task
  * name, the second the signal number and the third (optional) the 
decimation
  * factor. If not specified the decimation factor is the prevoius one, 
by default
  * it's 1 that means that there's no decimation.
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */
class Start_Data : public XmlRpcServerMethod
{
public:
   Start_Data(XmlRpcServer* s) : XmlRpcServerMethod("Start_Data", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()<2 || params.size()>3) {
         status["str"]="Number of parameters in calling START_DATA 
incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(!Is_Target_Connected){
         status["str"]="Target not connected";
	    status["state"] = (int)0;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }

	if(!params[1].getType() == 2) {
         status["str"]="Signal Number incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }
     unsigned int index= (int)params[1];
     if(params.size()==3) {
		if(!params[2].getType() == 2) {
	        status["str"]="Decimation Number incorrect.";
	        status["state"]=(int)1;
		    result=status;
		    return;
	    }
	    unsigned int dec = (int)params[2];
	    if(Signals_Manager->Set_Dec(index,dec)==-1) {
	        status["str"]="Error in setting decimation.";
	        status["state"]=(int)1;
		    result=status;
		    return;
	    }
     }
	

     try{
	    sem_wait(&mutex);
	    int index= (int)params[1];
	    if(index>=0 && index<Num_Scopes){
             Signals_Manager->Start_Signal(index);
             if (Verbose) {
                 printf("Signal %d enabled\n",index);
             }
	        status["str"]="Signal Enabled";
		    status["state"] = 
(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
	    }
	    else {
	        status["str"]="Signal Number not correct";
		    status["state"] = (int)1;
	    }
	    sem_post(&mutex);       //Critical section ended. Socket thread is 
unlocked.
     }catch(XmlRpcException e){
     	std::cout << e.getMessage();
    	    sem_post(&mutex);
         status["str"]="Error in setting signal";
	    status["state"] = (int)1;
     }
     result=status;
   }

   std::string help() { return std::string("Request signals selected by 
the client"); }

} start_data(&s);


/** \class Stop_Data
  * \brief It allows you to stop the data sending from the specified 
signal.
  *
  * This method is available as web service. It allows you to stop the data
  * sending from a signal.
  * @param params it has to contain two elements. The first is the task
  * name, the second the signal number.
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */

class Stop_Data : public XmlRpcServerMethod
{
public:
   Stop_Data(XmlRpcServer* s) : XmlRpcServerMethod("Stop_Data", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()!=2) {
         status["str"]="Number of parameters in calling STOP_DATA 
incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(!Is_Target_Connected){
         status["str"]="Target not connected";
	    status["state"] = (int)0;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }

	if(!params[1].getType() == 2) {
         status["str"]="Signal Number incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }

     try{
	    sem_wait(&mutex);
	    int index= (int)params[1];
	    if(index>=0 && index<Num_Scopes){
             Signals_Manager->Stop_Signal(index);
             if (Verbose) {
                 printf("Signal %d disabled\n",index);
             }
	        status["str"]="Signal Disabled";
		    status["state"] = 
(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
	    }
	    else {
	        status["str"]="Signal Number not correct";
		    status["state"] = (int)1;
	    }
	    sem_post(&mutex);
     }catch(XmlRpcException e){
     	std::cout << e.getMessage();
    	    sem_post(&mutex);
         status["str"]="Error in resetting signal";
	    status["state"] = (int)1;
     }
     result=status;
   }

   std::string help() { return std::string("Request signals selected by 
the client"); }

} stop_data(&s);    // This constructor registers the method with the server

/** \class Stop_All_Data
  * \brief It allows you to stop the data sending of all signals.
  *
  * This method is available as web service. It allows you to stop the 
sending of
  * all signals to send the data over the net using the open socket without
  * decimation.
  * @param params it has to contain as element 0 the task name.
  * @param result This variable contains the result of the execution of 
this
  * function. It contains two values. The first "str" is an human readable
  * string that explains what's happened. The second "state" is an 
integer value
  * that contains the state of the system (target+server) and can be 
explained in
  * this way. The first four bits contains the useful information. The 
less one
  * indicates if an error occurred, the second shows if the target 
exists, the third
  * let you know if the target is connected to the server and the last 
if the
  * connected target is running.
  *
  * @return see parameter result.
  */

class Stop_All_Data : public XmlRpcServerMethod
{
public:
   Stop_All_Data(XmlRpcServer* s) : XmlRpcServerMethod("Stop_All_Data", 
s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
   	if(!params.valid() || params.size()!=1) {
         status["str"]="Number of parameters in calling STOP_ALL_DATA 
incorrect";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
     if(!Is_Target_Connected){
         status["str"]="Target not connected";
	    status["state"] = (int)0;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(TargetName)) {
         status["str"]="Taskname incorrect.";
         status["state"]=(int)1;
	    result=status;
	    return;
     }
	if(!Is_There_A_Target(TargetName)) {
         status["str"]="No "+TargetName+" target or bad interface task 
identifier";
         status["state"]=(int)0;
	    result=status;
	    return;
     }

     try{
	    sem_wait(&mutex);
         Signals_Manager->ResetAll();
         status["str"]="All Signals Disabled";
	    status["state"] = 
(int)((Is_Target_Running*8+Is_Target_Connected*4+2));
	    sem_post(&mutex);       //Critical section ended. Socket thread is 
unlocked.
     }catch(XmlRpcException e){
    	    sem_post(&mutex);
         status["str"]="Error in resetting signals";
	    status["state"] = (int)1;
     }
     result=status;
   }

   std::string help() { return std::string("Reset all signals."); }

} stop_all_data(&s);    // This constructor registers the method with 
the server

class RunTarget : public XmlRpcServerMethod
{
public:
   RunTarget(XmlRpcServer* s) : XmlRpcServerMethod("RunTarget", s) {}

   void execute(XmlRpcValue& params, XmlRpcValue& result)
   {
     XmlRpcValue status;
     pid_t childpid;
     std::string target_to_run("");
     std::string base=target_directory;
   	if(!params.valid() || params.size()<1 || params.size()>2) {
         status["str"]="Number of parameters in calling RUNTARGET 
incorrect";
         status["error"]=(int)1;
	    result=status;
	    return;
     }
     if(std::string(params[0]).compare(ServerName)) {
         status["str"]="Servername incorrect.";
         status["error"]=(int)1;
	    result=status;
	    return;
     }
     target_to_run=std::string(params[1]);
	base+=target_to_run;
     childpid = fork();
     if (childpid >= 0)
     {
         if (childpid == 0)
         {
			listen_sock.Close();
			s.shutdown();
             execl("./rtarget","rtarget","",0);
             exit(0);
         }
         else
             wait(NULL);
     }
     else
     {
         perror("fork");
         exit(0);
     }

     status["str"] = std::string("Target ") + target_to_run + " avviato 
correttamente";
     status["error"] = (int)0;
     result = status;
    }

   std::string help() { return std::string("Allows to run a Target"); }

} runtarget(&s);    // This constructor registers the method with the server



void rlg_read_pref(void)
{
             Preferences.Target_IP = "127.0.0.1";
             Preferences.Target_Interface_Task_Name= "IFTASK";
             Preferences.Target_Scope_Mbx_ID = "RTS";
             Preferences.Target_Log_Mbx_ID = "RTL";
             Preferences.Target_Led_Mbx_ID = "RTE";
             Preferences.Target_Meter_Mbx_ID = "RTM";
             Preferences.Target_Synch_Mbx_ID = "RTY";
}

/** \brief Stop the server.
  *
  * This function stops the server execution in a safe way. It 
disconnects the
  * target from the server, kills all thread and stops the external 
interface. *
  *
  */
void rlg_quit_cb(void)
{
     if (Is_Target_Connected) {
         RT_RPC(Target_Interface_Task, DISCONNECT_FROM_TARGET, 0);
     }
     else
         if(!client_connected && client_waiting) {
			Socket data_sock;
			data_sock.create();
			data_sock.connect("localhost",portSocket);
			client_connected=false;
			client_waiting=false;
			sending_sock.Close();
         }
     End_App = 1;
     for (int n = 0; n < Num_Scopes; n++) {
         pthread_join(Get_Scope_Data_Thread[n], NULL);
     }
     Signals_Manager->ResetAll();
	listen_sock.Close();
     rt_send(Target_Interface_Task, CLOSE);
     pthread_join(Target_Interface_Thread, NULL);
     End_All = 1;
     return;
}

void rlg_batch_update_parameters_cb(void)
{
     int i, n;

     for (i = n = 0; i < Parameters_Manager->batch_counter(); i++) {
         n += 
Parameters_Manager->update_parameter(Batch_Parameters[i].index, 
Batch_Parameters[i].mat_index, Batch_Parameters[i].value);
     }
     if (Parameters_Manager->batch_counter() > 0 && n == 
Parameters_Manager->batch_counter()) {
         RT_RPC(Target_Interface_Task, BATCH_DOWNLOAD, 0);
		Parameters_Manager->batch_counter( 0);
     }
}

/*
This allows to update more than one parameter at the time.
If the checkbox batch_download is disabled, task_interface is called 
with code UPDATE_PARAM,
otherwise there is no update and the new values are pushed into 
Batch_Parameters.
*/
void rlg_update_parameters_cb(int ind, int map_offset, double value)
{
     RT_RPC(Target_Interface_Task, (ind << 20) | (map_offset << 4) | 
UPDATE_PARAM, 0);
}

void Target_Ended(int ID_Caller)
{
     Is_Target_Connected = 0;
     Signals_Manager->ResetAll();
     for (int n = 0; n < Num_Scopes; n++)
     {
     	if(n!=ID_Caller)
	        pthread_join(Get_Scope_Data_Thread[n], NULL);
     }
	sem_wait(&mutex_sock);
	sending_sock.Close();
     pthread_join(Send_Data_Target_Thread, NULL);					

     if (Verbose) {
         printf("Stopping real time code...");
     }

     rt_release_port(Target_Node, RPC_port);
     Target_Node = 0;
	RPC_port=0;
	
}



static void *rt_get_signal_data(void *arg)
{
     RT_TASK *GetScopeDataTask;
     MBX *GetScopeDataMbx;
     char GetScopeDataMbxName[7];
     long GetScopeDataPort;
     int MsgData = 0, MsgLen, MaxMsgLen, TracesBytes, MsgWait;
     float MsgBuf[MAX_MSG_LEN/sizeof(float)];
     int n, nn, jl;
     int index = ((Args_T *)arg)->index;
     char *mbx_id = strdup(((Args_T *)arg)->mbx_id);
     unsigned short Number_Samples=0;
     unsigned short Prefix_Number=0;
     unsigned short Actual_Dec=Signals_Manager->Get_Dec(index);
	int error_socket=0;

     rt_allow_nonroot_hrt();
     if (!(GetScopeDataTask = rt_task_init_schmod(get_an_id("HGS"), 99, 
0, 0, SCHED_RR, 0xFF))) {
         printf("Cannot init Host GetScopeData Task\n");
         return (void *)1;
     }
     if(Target_Node == 0) GetScopeDataPort = 0;
     else GetScopeDataPort = rt_request_port(Target_Node);
     sprintf(GetScopeDataMbxName, "%s%d", mbx_id, index);
     if (!(GetScopeDataMbx = (MBX *)RT_get_adr(Target_Node, 
GetScopeDataPort, GetScopeDataMbxName))) {
         printf("Error in getting %s mailbox address\n", 
GetScopeDataMbxName);
         return (void *)1;
     }
     TracesBytes = (Scopes[index].ntraces + 1)*sizeof(float);
     MaxMsgLen = 
(MAX_MSG_LEN>TracesBytes)?(MAX_MSG_LEN/TracesBytes)*TracesBytes:TracesBytes;
     MsgLen = 
(((int)(TracesBytes*REFRESH_RATE*(1./Scopes[index].dt)))/TracesBytes)*TracesBytes;
     if (MsgLen < TracesBytes) MsgLen = TracesBytes;
     if (MsgLen > MaxMsgLen) MsgLen = MaxMsgLen;
     MsgData = MsgLen/TracesBytes;
     MsgWait = 
(int)(((int)((MAX_MSG_SIZE-MsgLen)/TracesBytes))*Scopes[index].dt*1000);
     MsgWait=(MsgWait>WAIT_MIN)?MsgWait:WAIT_MIN;
     MsgWait=(MsgWait<WAIT_MAX)?MsgWait:WAIT_MAX;

     rt_send(Target_Interface_Task, 0);

     while (error_socket<11) {
         if (End_App || !Is_Target_Connected) break;
         while (RT_mbx_receive_if(Target_Node, GetScopeDataPort, 
GetScopeDataMbx, &MsgBuf, MsgLen)) {
             if (End_App || !Is_Target_Connected) {
             	if (Verbose) {
         			printf("Deleting scope thread number...%d\n", index);
			    }
			    rt_release_port(Target_Node, GetScopeDataPort);
			    rt_task_delete(GetScopeDataTask);
			    return 0;
             }
			if(!Is_There_A_Target(TargetName)) {
                 if (Verbose) {
                     printf("Target not found in rt_get_signal_data. 
Stopping...\n");
                     fflush(stdout);
                 }
                 if (Verbose) {
                     printf("\n...stopped.\n");
                     fflush(stdout);
                 }
         	}

             msleep(MsgWait);
         }


         if (Signals_Manager->Get_Signal(index)) {
             jl = 0;
             for (n = 0; n < MsgData; n++) {
				Number_Samples++;
             	if(Number_Samples%Signals_Manager->Get_Dec(index)==0)
             	{
             		Number_Samples=0;
	                char temp[20];
	                sprintf(temp,"%d",index);
	                std::string data(temp);
					Prefix_Number++;
					if(Prefix_Number==0)
						Prefix_Number=1;
					if(Actual_Dec!=Signals_Manager->Get_Dec(index)) {
						Prefix_Number=0;
						Actual_Dec=Signals_Manager->Get_Dec(index);
					}
                     sprintf(temp," %d",Prefix_Number);
                     data=data + temp;
	                for (nn = 1, jl++; nn < Scopes[index].ntraces + 1; nn++) {
	                    sprintf(temp," %e",MsgBuf[jl++]);
	                    data=data + temp;
	                }
		            if(sem_wait(&mutex_sock)==-1)
		            	std::cout<<"Error " << index;
					try{
						sending_sock << data + "\n";
					}
					catch (SocketException e) {
						if(Verbose)
							std::cout<<e.description()<<"\t"<<data<<"\n";
					}					
			        sem_post(&mutex_sock);
             	}
             	else
             		jl+=(Scopes[index].ntraces + 1);
             	
             }
         }
     }

     if (Verbose) {
         printf("Deleting scope thread number...%d\n", index);
     }
     rt_release_port(Target_Node, GetScopeDataPort);
     rt_task_delete(GetScopeDataTask);

     return 0;
}

void *rt_send_data_target(void *arg)
{
     try
     {
         client_connected=false;
         client_waiting=true;
         listen_sock.accept ( sending_sock );
         client_waiting=false;
         client_connected=true;
         sem_post(&mutex_sock);
     }
     catch ( SocketException& e )
     {
         std::cout << "Exception was caught:" << e.description() << 
"\nExiting.\n";
     }
     pthread_exit(NULL);
     return 0;
}

double get_parameter(Target_Parameters_T p, int nr, int nc, int *val_idx)
{
     switch (p.data_class) {
         case rt_SCALAR:
             *val_idx = 0;
             return (p.data_value[0]);
         case rt_VECTOR:
             *val_idx = nc;
             return (p.data_value[nc]);
         case rt_MATRIX_ROW_MAJOR:
             *val_idx = nr*p.n_cols+nc;
             return (p.data_value[nr*p.n_cols+nc]);
         case rt_MATRIX_COL_MAJOR:
             *val_idx = nc*p.n_rows+nr;
             return (p.data_value[nc*p.n_rows+nr]);
         default:
             return (0.0);
     }
}

static void try_to_connect(const char *IP)
{
     int counter = 0;
     int counter_max = 5;
     char buf[100];
     struct sockaddr_in addr;

     sprintf(buf, "Trying to connect to %s", IP);

     if (Verbose) {
         printf("%s...", buf);
         fflush(stdout);
     }
     inet_aton(IP, &addr.sin_addr);
     Target_Node = addr.sin_addr.s_addr;
     while ((RPC_port = rt_request_port(Target_Node)) <= 0 && counter++ 
<= counter_max) {
         msleep(100);
     }
     if(Verbose){
         printf("using port %f", (float)RPC_port);
     }
     msleep(100);
}


/*  This is used in Target_Interface_Task during a (CONNECT_TO_TARGET) 
to get the number of tunable parameters
     and define the struct Tunable_Parameters.
*/
static int get_parameters_info(/*long port,*/ RT_TASK *task)
{
     unsigned int req = 'c';
     char c_req = 'i';
     int blk_index = 0;
     int n_params = 0;

     RT_rpc(Target_Node, RPC_port, task, req, &Is_Target_Running);
     n_params = Is_Target_Running & 0xffff;
     Is_Target_Running >>= 16;
     if (n_params > 0) Tunable_Parameters = new Target_Parameters_T 
[n_params];
     else               Tunable_Parameters = new Target_Parameters_T [1];

     RT_rpcx(Target_Node, RPC_port, task, &c_req, 
&Tunable_Parameters[0], sizeof(char), sizeof(Target_Parameters_T));
     RLG_Target_Name = strdup(Tunable_Parameters[0].model_name);

     for (int n = 0; n < n_params; n++) {
         RT_rpcx(Target_Node, RPC_port, task, &c_req, 
&Tunable_Parameters[n], sizeof(char), sizeof(Target_Parameters_T));
         if (n > 0) {
             if (strcmp(Tunable_Parameters[n-1].block_name, 
Tunable_Parameters[n].block_name)) {
                 Num_Tunable_Blocks++;
             }
         } else {
             Num_Tunable_Blocks = 1;
         }
     }
     if (Num_Tunable_Blocks > 0) Tunable_Blocks = new Target_Blocks_T 
[Num_Tunable_Blocks];
     blk_index = 0;
     for (int n = 0; n < n_params; n++) {
         if (n > 0) {
             if (strcmp(Tunable_Parameters[n-1].block_name, 
Tunable_Parameters[n].block_name)) {
                 blk_index++;
                 strncpy(Tunable_Blocks[blk_index].name, 
Tunable_Parameters[n].block_name + 
strlen(Tunable_Parameters[0].model_name) + 1, MAX_NAMES_SIZE);
                 Tunable_Blocks[blk_index].offset = n;
             }
         } else {
             strncpy(Tunable_Blocks[0].name, 
Tunable_Parameters[0].block_name + 
strlen(Tunable_Parameters[0].model_name) + 1, MAX_NAMES_SIZE);
             Tunable_Blocks[0].offset = 0;
         }
     }

     return n_params;
}

static void upload_parameters_info(RT_TASK *task)
{
     unsigned int req = 'g';
     char c_req = 'i';
     int n;

	if(Is_There_A_Target(TargetName)) {
	    RT_rpc(Target_Node, RPC_port, task, req, &Is_Target_Running);
	    if (Verbose) {
	        printf("Upload parameters...\n");
	    }
	    for (n = 0; n < Num_Tunable_Parameters; n++) {
	        RT_rpcx(Target_Node, RPC_port, task, &c_req, 
&Tunable_Parameters[n], sizeof(char), sizeof(Target_Parameters_T));
	    }
	}
     else {
	    RT_RPC(Target_Interface_Task, STOP_TARGET, 0);
         if (Verbose)
             printf("Target not found in upload_parameters.\n");
	}
}

static int get_scope_blocks_info(/*long port,*/ RT_TASK *task, const 
char *mbx_id)
{
     int n_scopes = 0;
     int req = -1, msg;

     for (int n = 0; n < MAX_RTAI_SCOPES; n++) {
         char mbx_name[7];
         sprintf(mbx_name, "%s%d", mbx_id, n);
         if (!RT_get_adr(Target_Node, RPC_port, mbx_name)) {
             n_scopes = n;
             break;
         }
     }
     if (n_scopes > 0) Scopes = new Target_Scopes_T [n_scopes];
     for (int n = 0; n < n_scopes; n++) {
         char scope_name[MAX_NAMES_SIZE];
         Scopes[n].visible = false;
         RT_rpcx(Target_Node, RPC_port, task, &n, &Scopes[n].ntraces, 
sizeof(int), sizeof(int));
         RT_rpcx(Target_Node, RPC_port, task, &n, &scope_name, 
sizeof(int), sizeof(scope_name));
         strncpy(Scopes[n].name, scope_name, MAX_NAMES_SIZE);
         RT_rpcx(Target_Node, RPC_port, task, &n, &Scopes[n].dt, 
sizeof(int), sizeof(float));
     }
     RT_rpcx(Target_Node, RPC_port, task, &req, &msg, sizeof(int), 
sizeof(int));

     return n_scopes;
}

static int get_log_blocks_info(/*long port, */RT_TASK *task, const char 
*mbx_id)
{
     int n_logs = 0;
     int req = -1, msg;
	
     for (int n = 0; n < MAX_RTAI_LOGS; n++) {
         char mbx_name[7];
         sprintf(mbx_name, "%s%d", mbx_id, n);
         if (!RT_get_adr(Target_Node, RPC_port, mbx_name)) {
             n_logs = n;
             break;
         }
     }

     if (n_logs > 0) Logs = new Target_Logs_T [n_logs];
     for (int n = 0; n < n_logs; n++) {
         char log_name[MAX_NAMES_SIZE];
         RT_rpcx(Target_Node, RPC_port, task, &n, &Logs[n].nrow, 
sizeof(int), sizeof(int));
         RT_rpcx(Target_Node, RPC_port, task, &n, &Logs[n].ncol, 
sizeof(int), sizeof(int));
         RT_rpcx(Target_Node, RPC_port, task, &n, &log_name, 
sizeof(int), sizeof(log_name));
         strncpy(Logs[n].name, log_name, MAX_NAMES_SIZE);
         RT_rpcx(Target_Node, RPC_port, task, &n, &Logs[n].dt, 
sizeof(int), sizeof(float));
     }
     RT_rpcx(Target_Node, RPC_port, task, &req, &msg, sizeof(int), 
sizeof(int));

     return n_logs;
}

static int get_led_blocks_info(/*long port,*/ RT_TASK *task, const char 
*mbx_id)
{
     int n_leds = 0;
     int req = -1, msg;

     for (int n = 0; n < MAX_RTAI_LEDS; n++) {
         char mbx_name[7];
         sprintf(mbx_name, "%s%d", mbx_id, n);
         if (!RT_get_adr(Target_Node, RPC_port, mbx_name)) {
             n_leds = n;
             break;
         }
     }
     if (n_leds > 0) Leds = new Target_Leds_T [n_leds];
     for (int n = 0; n < n_leds; n++) {
         char led_name[MAX_NAMES_SIZE];
         Leds[n].visible = false;
         RT_rpcx(Target_Node, RPC_port, task, &n, &Leds[n].n_leds, 
sizeof(int), sizeof(int));
         RT_rpcx(Target_Node, RPC_port, task, &n, &led_name, 
sizeof(int), sizeof(led_name));
         strncpy(Leds[n].name, led_name, MAX_NAMES_SIZE);
         RT_rpcx(Target_Node, RPC_port, task, &n, &Leds[n].dt, 
sizeof(int), sizeof(float));
     }
     RT_rpcx(Target_Node, RPC_port, task, &req, &msg, sizeof(int), 
sizeof(int));

     return n_leds;
}

static int get_meter_blocks_info(/*long port,*/ RT_TASK *task, const 
char *mbx_id)
{
     int n_meters = 0;
     int req = -1, msg;

     for (int n = 0; n < MAX_RTAI_METERS; n++) {
         char mbx_name[7];
         sprintf(mbx_name, "%s%d", mbx_id, n);
         if (!RT_get_adr(Target_Node, RPC_port, mbx_name)) {
             n_meters = n;
             break;
         }
     }
     if (n_meters > 0) Meters = new Target_Meters_T [n_meters];
     for (int n = 0; n < n_meters; n++) {
         char meter_name[MAX_NAMES_SIZE];
         Meters[n].visible = false;
         RT_rpcx(Target_Node, RPC_port, task, &n, &meter_name, 
sizeof(int), sizeof(meter_name));
         strncpy(Meters[n].name, meter_name, MAX_NAMES_SIZE);
         RT_rpcx(Target_Node, RPC_port, task, &n, &Meters[n].dt, 
sizeof(int), sizeof(float));
     }
     RT_rpcx(Target_Node, RPC_port, task, &req, &msg, sizeof(int), 
sizeof(int));

     return n_meters;
}

static int get_synch_blocks_info(/*long port,*/ RT_TASK *task, const 
char *mbx_id)
{
     int n_synchs = 0;
     int req = -1, msg;

     for (int n = 0; n < MAX_RTAI_SYNCHS; n++) {
         char mbx_name[7];
         sprintf(mbx_name, "%s%d", mbx_id, n);
         if (!RT_get_adr(Target_Node, RPC_port, mbx_name)) {
             n_synchs = n;
             break;
         }
     }
     if (n_synchs > 0) Synchs = new Target_Synchs_T [n_synchs];
     for (int n = 0; n < n_synchs; n++) {
         char synch_name[MAX_NAMES_SIZE];
         Synchs[n].visible = false;
         RT_rpcx(Target_Node, RPC_port, task, &n, &synch_name, 
sizeof(int), sizeof(synch_name));
         strncpy(Synchs[n].name, synch_name, MAX_NAMES_SIZE);
         RT_rpcx(Target_Node, RPC_port, task, &n, &Synchs[n].dt, 
sizeof(int), sizeof(float));
     }
     RT_rpcx(Target_Node, RPC_port, task, &req, &msg, sizeof(int), 
sizeof(int));

     return n_synchs;
}

void delete_all_pointers()
{
	if(Signals_Manager) {
		try{delete Signals_Manager;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Tunable_Parameters) {
		try{delete[] Tunable_Parameters;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Tunable_Blocks) {
		try{delete[] Tunable_Blocks;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Scopes) {
		try{delete[] Scopes;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Logs) {
		try{delete[] Logs;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Leds) {
		try{delete[] Leds;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Meters) {
		try{delete[] Meters;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Synchs) {
		try{delete[] Synchs;}
		catch(...)
		{std::cout<<"Error";}
	}
	if(Get_Scope_Data_Thread) {
		try{delete Get_Scope_Data_Thread;}
		catch(...)
		{std::cout<<"Error";}
	}
}

static void *rt_target_interface(void *args)
{
     unsigned int code, U_Request;
     RT_TASK *If_Task = NULL, *task;
     unsigned int msg;

     rt_allow_nonroot_hrt();
     if (!(Target_Interface_Task = 
rt_task_init_schmod(get_an_id("HTI2"), 98, 0, 0, SCHED_FIFO, 0xFF))) {
         printf("Cannot init Target_Interface_Task\n");
         exit(1);
     }
     rt_send(RLG_Main_Task, 0);
     msleep(100);

     while (!End_App) {
         if (!(task = rt_receive(0, &code))) continue;
         if (Verbose) {
             printf("Received code %d from task %p\n", code, task);
         }
         switch (code & 0xf) {

             case CONNECT_TO_TARGET:
				if(Verbose)
					std::cout<<"Begin CONNECT \n";
				try{listen_sock.Reset();}
				catch (SocketException e) {std::cout<<"Error in connect ricreazione 
del socket\n";}
                 if (Verbose)
                     printf("Reading target settings\n");
                 if (!strcmp(Preferences.Target_IP, "0")) {
                     Target_Node = 0;
                 } else {
					try_to_connect(Preferences.Target_IP);
                     if (RPC_port <= 0) {
                         if (Verbose) {
                             printf(" Sorry, no route to target\n");
                         }
                         RT_RETURN(task, CONNECT_TO_TARGET);
                         break;
                     }
                 }

                 if (!(If_Task = (RT_TASK *)RT_get_adr(Target_Node, 
RPC_port, TargetName.c_str()))) {
                     if (Verbose) {
                         printf("No target or bad interface task 
identifier\n");
                     }
                     RT_RETURN(task, CONNECT_TO_TARGET);
                     break;
                 }
                 Num_Tunable_Parameters = get_parameters_info(If_Task);
                 if (Verbose) {
                     printf("Target is running...%s\n", 
Is_Target_Running ? "yes" : "no");
                     printf("Number of target tunable 
parameters...%d\n", Num_Tunable_Parameters);
                     for (int n = 0; n < Num_Tunable_Parameters; n++) {
                         printf("Block: %s\n", 
Tunable_Parameters[n].block_name);
                         printf(" Parameter: %s\n", 
Tunable_Parameters[n].param_name);
                         printf(" Number of rows: %d\n", 
Tunable_Parameters[n].n_rows);
                         printf(" Number of cols: %d\n", 
Tunable_Parameters[n].n_cols);
                         for (unsigned int nr = 0; nr < 
Tunable_Parameters[n].n_rows; nr++) {
                             for (unsigned int nc = 0; nc < 
Tunable_Parameters[n].n_cols; nc++) {
                                 printf(" Value    : %f\n", 
Tunable_Parameters[n].data_value[nr*Tunable_Parameters[n].n_cols+nc]);
                             }
                         }
                     }
                 }
                 Num_Scopes = get_scope_blocks_info(/*Target_Port,*/ 
If_Task, ScopeMbxName.c_str());
                 Signals_Manager=new Signal_Manager();
                 if (Verbose) {
                     printf("Number of target real time scopes: %d\n", 
Num_Scopes);
                     for (int n = 0; n < Num_Scopes; n++) {
                         printf("Scope: %s\n", Scopes[n].name);
                         printf(" Number of traces...%d\n", 
Scopes[n].ntraces);
                         printf(" Sampling time...%f\n", Scopes[n].dt);
                     }
                 }
                 get_log_blocks_info(/*Target_Port, */If_Task, 
Preferences.Target_Log_Mbx_ID);
                 get_led_blocks_info(/*Target_Port, */If_Task, 
Preferences.Target_Led_Mbx_ID);
                 get_meter_blocks_info(/*Target_Port, */If_Task, 
Preferences.Target_Meter_Mbx_ID);
                 get_synch_blocks_info(/*Target_Port, */If_Task, 
Preferences.Target_Synch_Mbx_ID);
                 Is_Target_Connected = 1;
                 if (Verbose) {
                     printf("Target %s is correctly connected\n", 
RLG_Target_Name);
                 }
                 if (Num_Scopes > 0) Get_Scope_Data_Thread = new 
pthread_t [Num_Scopes];
                 for (int n = 0; n < Num_Scopes; n++) {
                     unsigned int msg;
                     Args_T thr_args;
                     thr_args.index = n;
                     thr_args.mbx_id = strdup(ScopeMbxName.c_str());
                     thr_args.x = 500;
                     thr_args.y = 290;
                     thr_args.w = 250;
                     thr_args.h = 250;
                     pthread_create(&Get_Scope_Data_Thread[n], NULL, 
rt_get_signal_data, &thr_args);
                     rt_receive(0, &msg);
                 }
			    pthread_create(&Send_Data_Target_Thread, NULL, 
rt_send_data_target, &msg);
                 RT_RETURN(task, CONNECT_TO_TARGET);
				if(Verbose)
	                std::cout<<"end CONNECT\n";
                 break;
             case DISCONNECT_FROM_TARGET:
				if(Verbose)
	                std::cout<<"Begin DISCONNECT\n";
                 if (Verbose)
                     printf("Disconnecting from target %s\n", 
Tunable_Parameters[0].model_name);
                 Is_Target_Connected = 0;
                 if (Verbose)
					std::cout<<"Reset all signals...";
                 Signals_Manager->ResetAll();
                 if (Verbose){
					std::cout<<"done.\n";
					std::cout<<"Client_connected: "<<client_connected<<"\n";
                 }
                 if(!client_connected && client_waiting) {
					Socket data_sock;
					data_sock.create();
					data_sock.connect("localhost",portSocket);
					client_connected=false;
					client_waiting=false;
                 }

                 for (int n = 0; n < Num_Scopes; n++) {
                     pthread_join(Get_Scope_Data_Thread[n], NULL);
                 }
				sem_wait(&mutex_sock);
             	sending_sock.Close();
                 pthread_join(Send_Data_Target_Thread, NULL);
             	
                 rt_release_port(Target_Node, RPC_port/*Target_Port*/);
				RPC_port=0;
                 free(Tunable_Parameters);
                 RT_RETURN(task, DISCONNECT_FROM_TARGET);
				if(Verbose)
					std::cout<<"End DISCONNECT.\n";
                 break;

             case START_TARGET:
				if(Verbose)
					std::cout<<"Begin START...";
                 if (!Is_Target_Running) {
                     if (Verbose) {
                         printf("Starting real time code...");
                     }
                     U_Request = 's';
					if(Is_There_A_Target(TargetName)) {
	                    RT_rpc(Target_Node, /*Target_Port*/RPC_port, 
If_Task, U_Request, &Is_Target_Running);
                 	}
	                else {
					    RT_RPC(Target_Interface_Task, STOP_TARGET, 0);
	                    if (Verbose)
	                        printf("Target not found in START_TARGET.\n");
                 	}
                 }
                 RT_RETURN(task, START_TARGET);
				if(Verbose)
					std::cout<<"End START.\n";
                 break;

             case STOP_TARGET:
				if(Verbose)
					std::cout<<"Begin STOP...\n";

                 if (Is_Target_Running) {
                     U_Request = 't';

	                Is_Target_Connected = 0;
	                if (Verbose)
						std::cout<<"Reset all signals...";
	                Signals_Manager->ResetAll();
	                if (Verbose)
						std::cout<<"done.\n";
	                if(!client_connected && client_waiting) {
						Socket data_sock;
						data_sock.create();
						data_sock.connect("localhost",portSocket);
						client_connected=false;
						client_waiting=false;
	                }
	
	                for (int n = 0; n < Num_Scopes; n++)
	                    pthread_join(Get_Scope_Data_Thread[n], NULL);
					sem_wait(&mutex_sock);
	            	sending_sock.Close();
	                pthread_join(Send_Data_Target_Thread, NULL);					

                     if (Verbose) {
                         printf("Stopping real time code...");
                     }

					if(Is_There_A_Target(TargetName))
	                    RT_rpc(Target_Node, /*Target_Port*/RPC_port, 
If_Task, U_Request, &Is_Target_Running);
                     rt_release_port(Target_Node, RPC_port/*Target_Port*/);
                     Target_Node = 0;
					RPC_port=0;
                 }
                 RT_RETURN(task, STOP_TARGET);
				if(Verbose)
					std::cout<<"End STOP.\n";
                 break;

             case UPDATE_PARAM: {

                 U_Request = 'p';
                 int Map_Offset = (code >> 4) & 0xffff;
                 int Mat_Idx = (code >> 20) & 0xfff;
                 int Is_Param_Updated;
                 double new_value = 
(double)Tunable_Parameters[Map_Offset].data_value[Mat_Idx];

				if(Is_There_A_Target(TargetName)) {
	                RT_rpc(Target_Node, RPC_port/*Target_Port*/, If_Task, 
U_Request, &Is_Target_Running);
	                RT_rpcx(Target_Node, RPC_port/*Target_Port*/, If_Task, 
&Map_Offset, &Is_Param_Updated, sizeof(int), sizeof(int));
	                RT_rpcx(Target_Node, RPC_port/*Target_Port*/, If_Task, 
&new_value, &Is_Param_Updated, sizeof(double), sizeof(int));
	                RT_rpcx(Target_Node, RPC_port/*Target_Port*/, If_Task, 
&Mat_Idx, &Is_Param_Updated, sizeof(int), sizeof(int));
             	}
                 else {
				    RT_RPC(Target_Interface_Task, STOP_TARGET, 0);
                     if (Verbose)
                         printf("Target not found in UPDATE_PARAM.\n");
             	}
                 RT_RETURN(task, UPDATE_PARAM);
                 break;
             }
             case BATCH_DOWNLOAD: {

                 U_Request = 'd';
                 int Is_Param_Updated;
                 int Counter = Parameters_Manager->batch_counter();

				if(Is_There_A_Target(TargetName)) {
	                RT_rpc(Target_Node, RPC_port/*Target_Port*/, If_Task, 
U_Request, &Is_Target_Running);
	                RT_rpcx(Target_Node, RPC_port/*Target_Port*/, If_Task, 
&Counter, &Is_Param_Updated, sizeof(int), sizeof(int));
	                RT_rpcx(Target_Node, RPC_port/*Target_Port*/, If_Task, 
&Batch_Parameters, &Is_Param_Updated, 
sizeof(Batch_Parameters_T)*Counter, sizeof(int));
                     if (Verbose)
                         printf("ok\n");
             	}
                 else {
				    RT_RPC(Target_Interface_Task, STOP_TARGET, 0);
                     if (Verbose)
                         printf("Target not found in BATCH_DOWNLOAD.\n");
             	}
                 RT_RETURN(task, BATCH_DOWNLOAD);
                 break;
             }

             case GET_PARAMS: {
                 upload_parameters_info(/*Target_Port, */If_Task);
                 if (Verbose) {
                     printf("Target is running...%s\n", 
Is_Target_Running ? "yes" : "no");
                     printf("Number of target tunable 
parameters...%d\n", Num_Tunable_Parameters);
                     for (int n = 0; n < Num_Tunable_Parameters; n++) {
                         printf("Block: %s\n", 
Tunable_Parameters[n].block_name);
                         printf(" Parameter: %s\n", 
Tunable_Parameters[n].param_name);
                         printf(" Number of rows: %d\n", 
Tunable_Parameters[n].n_rows);
                         printf(" Number of cols: %d\n", 
Tunable_Parameters[n].n_cols);
                         for (unsigned int nr = 0; nr < 
Tunable_Parameters[n].n_rows; nr++) {
                             for (unsigned int nc = 0; nc < 
Tunable_Parameters[n].n_cols; nc++) {
                                 printf(" Value    : %f\n", 
Tunable_Parameters[n].data_value[nr*Tunable_Parameters[n].n_cols+nc]);
                             }
                         }
                     }
                 }
                 RT_RETURN(task, GET_PARAMS);
                 break;
             }
             case CLOSE:
                 rt_task_delete(Target_Interface_Task);
                 return 0;
             default:
                 break;
         }
     }

     rt_task_delete(Target_Interface_Task);

     return 0;
}

struct option options[] = {
     { "help",       	0, 0, 'h' },
     { "target",       	0, 0, 't' },
     { "verbose",    	0, 0, 'v' },
     { "version",    	0, 0, 'V' },
     { "stop",    		0, 0, 's' },
     { "servername",		1, 0, 'n' },
     { "portXML",   		1, 0, 'X' },
     { "portSocket",    	1, 0, 'S' }
};


void print_usage(void)
{
     fputs(
("\nUsage:  rtaixml [OPTIONS]\n"
"\n"
"OPTIONS:\n"
"  -h, --help\n"
"      print usage\n"
"  -v, --verbose\n"
"      verbose output\n"
"  -t, --target\n"
"      allow specific script execution\n"
"  -V, --version\n"
"      print version\n"
"  -s, --stop\n"
"      stop server on localhost on the specified port\n"
"  -n, --servername <SERVER NAME>\n"
"      set the server name in the RTAI domain\n"
"  -X <XMLRPC_port>, --portXML <XMLRPC_port>\n"
"      number of the XMLRPC server port\n"
"  -S <Socket_port>, --portSocket <Socket_port>\n"
"      number of the Socket server port\n"
"\n")
         ,stderr);
     exit(0);
}

int main(int argc, char **argv)
{
     char *lang_env;
     int c, option_index = 0;
     unsigned int msg;
     int test;
	XmlRpcValue oneArgs, result;
     int verbosityXMLRPC=0;
	RT_TASK *Verify_Server;
	bool toStop=false;


     while (1) {
         c = getopt_long(argc, argv, "htvVn:sX:S:", options, &option_index);
         if (c == -1)
             break;
         switch (c) {
             case 'n':
				ServerName=std::string(optarg);
				std::cout<<"Server name set to "<<ServerName<<"\n";
				break;
             case 's':
             	toStop=true;
             	break;
             case 'v':
                 Verbose = 1;
		        verbosityXMLRPC=1;
                 break;
             case 'V':
                 fputs("rtaixml version " RTAIXML_VERSION "\nbased on 
XRTAI-Lab version " XRTAILAB_VERSION "\n", stderr);
                 exit(0);
             case 'X':
				if ((test = atoi(optarg)) && test>1024 && test<65537) {
					if(test==portSocket) {
						(portSocket==65536)?portSocket--:portSocket++;		
						std::cout << "\nThe given xmlrpc server port number is equal to 
the socket port one; \nmoving the socket port number to " << portSocket 
<< " and setting the xmlrpc server port number to " << test <<"\n";
					}	
					portXML=test;
				}
				else
					std::cout << "The given port number isn't correct, using default 
one.\n";
				printf("XMLRPC Port set to %d\n",portXML);
             	break;
		    case 'S':
				if ((test = atoi(optarg)) && test>1024 && test<65537) {
					if(test==portXML) {
						(portXML==65536)?portXML--:portXML++;		
						std::cout << "\nThe given socket port number is equal to the 
xmlrpc server port one; \nmoving the xmlrpc server port number to " << 
portXML << " and setting the socket port number to " << test <<"\n";
					}	
					portSocket=test;
				}
				else
					std::cout << "The given port number isn't correct, using default 
one.\n";
				printf("Socket Port set to %d\n",portSocket);
				break;
		    case 't':
				std::cout << ">>>>  rtaixml server is allowed to execute the scritpt 
'rtarget'.  <<<<\n";
                 script_execution=true;;
				break;
		    case 'h':
                 print_usage();
                 exit(0);
             default:
                 break;
         }
     }
	if(toStop)
	{
		printf("Stopping rtai-xml server on port %d...\n",portXML);
		oneArgs[0]=ServerName.c_str();
		if((new XmlRpcClient("localhost", portXML))->execute("Stop_Server", 
oneArgs, result))
			std::cout << result << "\n";
		else
			std::cout << "Server not found on port " << portXML << ".\n";
         exit(0);
	}

     lang_env = getenv("LANG");
     setenv("LANG", "en_US", 1);
     rt_allow_nonroot_hrt();

/************** CHECK ANOTHER SERVER RUNNING ************************/
     Verify_Server = rt_task_init_schmod(get_an_id("check"), 99, 0, 0, 
SCHED_FIFO, 0xFF);
     if (rt_get_adr(nam2num(ServerName.c_str()))) {
     	std::cout<<"There is an rtaixml server already running.\n";
	    rt_task_delete(Verify_Server);
     	return 0;
     }
     rt_task_delete(Verify_Server);
/*****************************************************************/

     if(daemon(1,Verbose)) {
     	std::cout << "Error in creating server process, execution stopped.\n";
     	exit(1);
     }
     if (!(RLG_Main_Task = 
rt_task_init_schmod(nam2num(ServerName.c_str()), 99, 0, 0, SCHED_FIFO, 
0xFF))) {
         printf("Cannot init RTAI_LAB main task\n");
         exit(1);
     }
     rlg_read_pref();
     pthread_create(&Target_Interface_Thread, NULL, rt_target_interface, 
NULL);
     rt_receive(0, &msg);
     msleep(100);
     sem_init(&mutex, 0, 1); /* initialize mutex to 1 - binary semaphore */
	                        /* second param = 0 - semaphore is local */

     if(sem_init(&mutex_sock, 0, 0)==-1)
     	std::cout<<"errore nel mutex_sock";

     std::cout << "running....\n";


     XmlRpc::setVerbosity(verbosityXMLRPC);
     s.bindAndListen(portXML);
     s.enableIntrospection(true);
     listen_sock.Active(portSocket);

     s.work(-1.0);
     return 0;
}

-- 
   ____
  /  |_| <<< IR. ARNO H.A. STIENEN >>>
|_ O  | Biomechanical Engineering | http://www.bw.ctw.utwente.nl
|_|__/  a.h.a.stienen at utwente.nl  | +31-(0)53-489-4778
UTwente "There are alternatives: Wouter Bos!"






More information about the Rtai mailing list