[Positioning] Add OutputTCPSocketEvAAL
This commit is contained in:
parent
3490b94df7
commit
d5fcfed1f2
|
@ -91,6 +91,7 @@ OBJ_LIST = \
|
||||||
outputterminal.o \
|
outputterminal.o \
|
||||||
outputcsv.o \
|
outputcsv.o \
|
||||||
outputudpsocket.o \
|
outputudpsocket.o \
|
||||||
|
outputtcpsocketevaal.o \
|
||||||
positioning.o \
|
positioning.o \
|
||||||
input.o \
|
input.o \
|
||||||
inputcsv.o \
|
inputcsv.o \
|
||||||
|
@ -246,6 +247,9 @@ $(OBJ_DIR)/outputcsv.o: \
|
||||||
$(OBJ_DIR)/outputudpsocket.o: \
|
$(OBJ_DIR)/outputudpsocket.o: \
|
||||||
$(SRC_DIR)/outputmedium.hh \
|
$(SRC_DIR)/outputmedium.hh \
|
||||||
$(OBJ_DIR)/result.o
|
$(OBJ_DIR)/result.o
|
||||||
|
$(OBJ_DIR)/outputtcpsocketevaal.o: \
|
||||||
|
$(SRC_DIR)/outputmedium.hh \
|
||||||
|
$(OBJ_DIR)/result.o
|
||||||
$(OBJ_DIR)/outputcsv.o: \
|
$(OBJ_DIR)/outputcsv.o: \
|
||||||
$(SRC_DIR)/outputmedium.hh \
|
$(SRC_DIR)/outputmedium.hh \
|
||||||
$(OBJ_DIR)/result.o
|
$(OBJ_DIR)/result.o
|
||||||
|
@ -253,6 +257,7 @@ $(OBJ_DIR)/output.o: \
|
||||||
$(OBJ_DIR)/outputterminal.o \
|
$(OBJ_DIR)/outputterminal.o \
|
||||||
$(OBJ_DIR)/outputcsv.o \
|
$(OBJ_DIR)/outputcsv.o \
|
||||||
$(OBJ_DIR)/outputudpsocket.o \
|
$(OBJ_DIR)/outputudpsocket.o \
|
||||||
|
$(OBJ_DIR)/outputtcpsocketevaal.o \
|
||||||
$(OBJ_DIR)/configuration.o \
|
$(OBJ_DIR)/configuration.o \
|
||||||
$(OBJ_DIR)/posexcept.o
|
$(OBJ_DIR)/posexcept.o
|
||||||
$(OBJ_DIR)/multilaterationalgorithm.o: \
|
$(OBJ_DIR)/multilaterationalgorithm.o: \
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "outputterminal.hh"
|
#include "outputterminal.hh"
|
||||||
#include "outputcsv.hh"
|
#include "outputcsv.hh"
|
||||||
#include "outputudpsocket.hh"
|
#include "outputudpsocket.hh"
|
||||||
|
#include "outputtcpsocketevaal.hh"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -57,6 +58,9 @@ void Output::initialise_output_media()
|
||||||
else if (*i == "UDP")
|
else if (*i == "UDP")
|
||||||
initialise_output_udp_socket() ;
|
initialise_output_udp_socket() ;
|
||||||
|
|
||||||
|
else if (*i == "TCPEvAAL")
|
||||||
|
initialise_output_tcpevaal_socket() ;
|
||||||
|
|
||||||
else
|
else
|
||||||
throw bad_configuration(
|
throw bad_configuration(
|
||||||
"The specified output medium « "+ *i +" » is unknown!") ;
|
"The specified output medium « "+ *i +" » is unknown!") ;
|
||||||
|
@ -70,18 +74,6 @@ void Output::initialise_output_terminal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Output::initialise_output_udp_socket()
|
|
||||||
{
|
|
||||||
if (! Configuration::is_configured("output.udp-host"))
|
|
||||||
throw missing_configuration(
|
|
||||||
"No remote UDP host specified in the configuration!") ;
|
|
||||||
|
|
||||||
output_media.push_back(
|
|
||||||
new OutputUDPSocket(Configuration::string_value("output.udp-host"),
|
|
||||||
Configuration::int_value("output.udp-port"))) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Output::initialise_output_csv()
|
void Output::initialise_output_csv()
|
||||||
{
|
{
|
||||||
if (! Configuration::is_configured("output.csv-file"))
|
if (! Configuration::is_configured("output.csv-file"))
|
||||||
|
@ -94,6 +86,24 @@ void Output::initialise_output_csv()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Output::initialise_output_udp_socket()
|
||||||
|
{
|
||||||
|
if (! Configuration::is_configured("output.udp-host"))
|
||||||
|
throw missing_configuration(
|
||||||
|
"No remote UDP host specified in the configuration!") ;
|
||||||
|
|
||||||
|
output_media.push_back(
|
||||||
|
new OutputUDPSocket(Configuration::string_value("output.udp-host"),
|
||||||
|
Configuration::int_value("output.udp-port"))) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Output::initialise_output_tcpevaal_socket()
|
||||||
|
{
|
||||||
|
output_media.push_back(new OutputTCPSocketEvAAL) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Output::write(const ResultList &results) const
|
void Output::write(const ResultList &results) const
|
||||||
{
|
{
|
||||||
for (vector<OutputMedium*>::const_iterator i = output_media.begin() ;
|
for (vector<OutputMedium*>::const_iterator i = output_media.begin() ;
|
||||||
|
|
|
@ -19,6 +19,7 @@ protected:
|
||||||
void initialise_output_terminal(void) ;
|
void initialise_output_terminal(void) ;
|
||||||
void initialise_output_csv(void) ;
|
void initialise_output_csv(void) ;
|
||||||
void initialise_output_udp_socket(void) ;
|
void initialise_output_udp_socket(void) ;
|
||||||
|
void initialise_output_tcpevaal_socket(void) ;
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
#include "outputtcpsocketevaal.hh"
|
||||||
|
#include "request.hh"
|
||||||
|
#include "resultlist.hh"
|
||||||
|
#include "posexcept.hh"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <cstdio> // For perror()
|
||||||
|
|
||||||
|
using namespace std ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* *** Constructors *** */
|
||||||
|
|
||||||
|
|
||||||
|
OutputTCPSocketEvAAL::OutputTCPSocketEvAAL(
|
||||||
|
const string &_remote_host,
|
||||||
|
const uint_fast16_t _remote_port):
|
||||||
|
remote_host(_remote_host), remote_port(_remote_port)
|
||||||
|
{
|
||||||
|
if (! init_socket())
|
||||||
|
throw error_opening_output_file("TCP socket") ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OutputTCPSocketEvAAL::~OutputTCPSocketEvAAL()
|
||||||
|
{
|
||||||
|
close_socket() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* *** Operations *** */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \em true if the socket were successfully opened.
|
||||||
|
* @return \em false in case of error.
|
||||||
|
*/
|
||||||
|
bool OutputTCPSocketEvAAL::init_socket()
|
||||||
|
{
|
||||||
|
sockfd = socket(AF_INET, SOCK_STREAM, 0) ;
|
||||||
|
if (sockfd < 0)
|
||||||
|
{
|
||||||
|
perror("TCP socket creation failed") ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in server_description ;
|
||||||
|
memset(&server_description, 0, sizeof(server_description)) ;
|
||||||
|
server_description.sin_family = AF_INET ;
|
||||||
|
// Server IP address:
|
||||||
|
server_description.sin_addr.s_addr = inet_addr(remote_host.c_str()) ;
|
||||||
|
// Listening port on the server:
|
||||||
|
server_description.sin_port = htons(remote_port) ;
|
||||||
|
|
||||||
|
int ret = connect(sockfd, (struct sockaddr *)&server_description,
|
||||||
|
sizeof(server_description)) ;
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
perror("Cannot bind the TCP socket") ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normally, the socket is closed automatically by the destructor. Use
|
||||||
|
* this if you want to close the socket prematurely.
|
||||||
|
* #sockfd is set to -1, even in case of error.
|
||||||
|
* @return \em true if the socket were successfully closed or were not
|
||||||
|
* opened.
|
||||||
|
* @return \em false in case of error.
|
||||||
|
*/
|
||||||
|
bool OutputTCPSocketEvAAL::close_socket()
|
||||||
|
{
|
||||||
|
if (sockfd >= 0)
|
||||||
|
{
|
||||||
|
if (close(sockfd))
|
||||||
|
{
|
||||||
|
perror("Cannot close TCP socket") ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockfd = -1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OutputTCPSocketEvAAL::write(const Result &result)
|
||||||
|
{
|
||||||
|
const Point3D &position = result.get_position() ;
|
||||||
|
long timestamp = 1234567l ; // FIXME
|
||||||
|
int area_of_interest = 0 ; // FIXME
|
||||||
|
|
||||||
|
ostringstream str ;
|
||||||
|
str
|
||||||
|
<< "OwlPS "
|
||||||
|
<< position.get_x() << ' '
|
||||||
|
<< position.get_y() << ' '
|
||||||
|
<< timestamp << ' '
|
||||||
|
<< area_of_interest << '\n' ;
|
||||||
|
|
||||||
|
if (send_data(str.str()))
|
||||||
|
acknowledge() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OutputTCPSocketEvAAL::write(const ResultList &results)
|
||||||
|
{
|
||||||
|
assert(results.get_results().size() == 1) ;
|
||||||
|
write(results.get_results()[0]) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the text buffer 'data'.
|
||||||
|
*/
|
||||||
|
bool OutputTCPSocketEvAAL::send_data(const string &data) const
|
||||||
|
{
|
||||||
|
ssize_t nsent = send(sockfd, data.c_str(), data.size(), 0) ;
|
||||||
|
if (nsent != static_cast<ssize_t>(data.size()))
|
||||||
|
{
|
||||||
|
perror("Error sending result data") ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
return true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool OutputTCPSocketEvAAL::acknowledge() const
|
||||||
|
{
|
||||||
|
char ack_buf[10] ;
|
||||||
|
ssize_t nrecv = recv(sockfd, ack_buf, 10, 0) ;
|
||||||
|
if (nrecv < 0)
|
||||||
|
perror("Error receiving acknowledgement") ;
|
||||||
|
|
||||||
|
ack_buf[9] = '\0' ;
|
||||||
|
string ack(ack_buf) ;
|
||||||
|
if (ack == "Published")
|
||||||
|
return true ;
|
||||||
|
|
||||||
|
if (ack == "NotParsed")
|
||||||
|
{
|
||||||
|
cerr << "TCP server error: string not parsed.\n" ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
cerr
|
||||||
|
<< "TCP server error: unknown acknoledgment string « "
|
||||||
|
<< ack << " ».\n" ;
|
||||||
|
return false ;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_
|
||||||
|
#define _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_
|
||||||
|
|
||||||
|
#include "outputmedium.hh"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <stdint.h> // <cstdint> is not C++ 98 compliant
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
/// Sends results to a remote host by TCP (EvAAL competition format)
|
||||||
|
/**
|
||||||
|
* The results are sent through an TCP socket as a string value,
|
||||||
|
* conforming to the EvAAL competition format.
|
||||||
|
*/
|
||||||
|
class OutputTCPSocketEvAAL: public OutputMedium
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int sockfd ;
|
||||||
|
std::string remote_host ;
|
||||||
|
uint_fast16_t remote_port ;
|
||||||
|
|
||||||
|
struct sockaddr_in server_info ;
|
||||||
|
struct sockaddr_in client_info ;
|
||||||
|
|
||||||
|
/** @name Operations */
|
||||||
|
//@{
|
||||||
|
/// Initialises the socket
|
||||||
|
bool init_socket(void) ;
|
||||||
|
/// Sends a string through the socket
|
||||||
|
bool send_data(const std::string &data) const ;
|
||||||
|
/// Receives and parse the acknowledgement from the server
|
||||||
|
bool acknowledge(void) const ;
|
||||||
|
//@}
|
||||||
|
|
||||||
|
public:
|
||||||
|
OutputTCPSocketEvAAL(const std::string &_remote_host = "127.0.0.1",
|
||||||
|
const uint_fast16_t _remote_port = 4444) ;
|
||||||
|
~OutputTCPSocketEvAAL(void) ;
|
||||||
|
|
||||||
|
/** @name Operations */
|
||||||
|
//@{
|
||||||
|
void write(const Result &result) ;
|
||||||
|
void write(const ResultList &results) ;
|
||||||
|
/// Closes the socket
|
||||||
|
bool close_socket(void) ;
|
||||||
|
//@}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_
|
|
@ -241,8 +241,9 @@ void UserInterface::fill_output_options()
|
||||||
options.add_options()
|
options.add_options()
|
||||||
("output.medium,O", po::value< vector<string> >()->composing(),
|
("output.medium,O", po::value< vector<string> >()->composing(),
|
||||||
"Medium to which the results will be wrote. You can specify"
|
"Medium to which the results will be wrote. You can specify"
|
||||||
" this option more than once. Allowed: Terminal, CSV, UDP."
|
" this option more than once."
|
||||||
" If this option is absent, results will be printed on the terminal.")
|
" Allowed: Terminal, CSV, UDP, TCPEvAAL."
|
||||||
|
" If this option is absent, the results are printed on the terminal.")
|
||||||
("output.csv-file", po::value<string>(),
|
("output.csv-file", po::value<string>(),
|
||||||
"CSV file to use for output (when output.medium = CSV).")
|
"CSV file to use for output (when output.medium = CSV).")
|
||||||
("output.udp-host", po::value<string>(),
|
("output.udp-host", po::value<string>(),
|
||||||
|
|
Loading…
Reference in New Issue