[Positioning] Add InputUDPSocket

The positioning server can now read the requests sent by the aggregator
via UDP. This data exchange does not concern (auto)calibration requests
yet.
This commit is contained in:
Matteo Cypriani 2011-03-18 10:37:06 +01:00
parent c3c319a7f1
commit 161157dae7
6 changed files with 228 additions and 6 deletions

View File

@ -40,7 +40,7 @@ owlps-listener: libowlps libowlps-client
@make -C $@
owlps-aggregator: libowlps
@make -C $@
owlps-positioning:
owlps-positioning: libowlps
@make -C $@
@ -61,7 +61,7 @@ install-owlps-listener: install-libowlps
@make -C $(subst install-,,$@) install
install-owlps-aggregator: install-libowlps
@make -C $(subst install-,,$@) install
install-owlps-positioning:
install-owlps-positioning: install-libowlps
@make -C $(subst install-,,$@) install

View File

@ -22,16 +22,20 @@ STYLE = astyle --style=gnu --formatted
CPPCHECK = cppcheck --enable=all
DOXYGEN = doxygen >/dev/null
# Compilation tools and flags
# Compilation tools
COLORGCC := $(shell which colorgcc >/dev/null 2>&1 ; echo $$?)
ifeq ($(COLORGCC), 0)
CXX = colorgcc
endif
# Flags
LIBOWLPS_DIR = ../libowlps
#DEBUG = -g
TESTSGXXFLAGS = -I$(TESTS_DIR) -I$(SRC_DIR) -I.
GXXFLAGS = $(DEBUG) -Wall -Wextra
GXXFLAGS = $(DEBUG) -Wall -Wextra -I$(LIBOWLPS_DIR)
LD = $(CXX)
LDFLAGS = -lstdc++ -lm -lrt -lboost_program_options
LDFLAGS = -lstdc++ -lm -lrt -lboost_program_options \
-L$(LIBOWLPS_DIR) -lowlps
# Targets
TARGET = owlps-positioning
@ -75,6 +79,7 @@ OBJ_LIST = \
positioning.o \
input.o \
inputcsv.o \
inputudpsocket.o \
inputlogcsv.o
OBJ_NOTEST_LIST = \
posexcept.o \
@ -184,11 +189,18 @@ $(OBJ_DIR)/inputcsv.o: \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/stock.o
$(OBJ_DIR)/inputudpsocket.o: \
$(OBJ_DIR)/inputmedium.o \
$(OBJ_DIR)/posexcept.o \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/stock.o
$(OBJ_DIR)/inputlogcsv.o: \
$(SRC_DIR)/inputlogmedium.hh \
$(OBJ_DIR)/request.o
$(OBJ_DIR)/input.o: \
$(OBJ_DIR)/inputcsv.o \
$(OBJ_DIR)/inputudpsocket.o \
$(OBJ_DIR)/inputlogcsv.o \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/configuration.o \

View File

@ -1,5 +1,6 @@
#include "input.hh"
#include "inputcsv.hh"
#include "inputudpsocket.hh"
#include "inputlogcsv.hh"
#include "calibrationrequest.hh"
#include "configuration.hh"
@ -56,6 +57,15 @@ void Input::initialise_input_medium()
InputCSV(Configuration::string_value("input.csv-file")) ;
}
if (medium_name == "UDP")
{
if (! Configuration::is_configured("input.udp-port"))
throw missing_configuration(
"No input UDP port specified in the configuration!") ;
medium = new
InputUDPSocket(Configuration::int_value("input.udp-port")) ;
}
else
throw bad_configuration(
"The specified input medium « "+ medium_name +" » is unknown!") ;

View File

@ -0,0 +1,142 @@
#include "inputudpsocket.hh"
#include "posexcept.hh"
#include "stock.hh"
#include <owlps.h>
#include <iostream>
#include <boost/tr1/unordered_map.hpp>
using namespace std ;
using std::tr1::unordered_map ;
/* *** Constructors *** */
InputUDPSocket::InputUDPSocket(const uint_fast16_t _port):
listening_port(_port)
{
if (! init_socket())
throw error_opening_input_file("UDP socket") ;
}
InputUDPSocket::~InputUDPSocket()
{
close_socket() ;
}
/* *** Operations *** */
/**
* @return true if the socket were successfully opened, false in case of
* error.
*/
bool InputUDPSocket::init_socket()
{
sockfd = owl_create_udp_listening_socket(listening_port) ;
return sockfd >= 0 ;
}
/**
* 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 InputUDPSocket::close_socket()
{
if (sockfd >= 0)
{
if (close(sockfd))
{
perror("Cannot close UDP socket") ;
return false ;
}
sockfd = -1 ;
}
return true ;
}
/**
* This function reads the next Request in the UDP input socket.
* It cannot read calibration requests.
*
* #sockfd should be opened before processing requests; otherwise,
* #current_request is \link Request::clear() cleared\endlink and a
* blank Request is returned.
*
* @return The read Request, or a blank Request in case of error (socket
* not opened, bad packet format).
*/
const Request& InputUDPSocket::get_next_request()
{
clear_current_request() ;
if (eof())
return *current_request ;
struct sockaddr_in client; // UDP client structure
socklen_t client_len = sizeof(client) ; // Size of clients
// Read the main request data
owl_request request ;
ssize_t nread = recvfrom(sockfd, &request, sizeof(request), 0,
(struct sockaddr *) &client, &client_len) ;
if (nread <= 0)
{
cerr << "No request received!" << endl ;
return *current_request ;
}
// Endianess conversions
request.request_time = owl_ntoh_timestamp(request.request_time) ;
request.nb_info = ntohs(request.nb_info) ;
// Mobile MAC
char *mac_mobile =
owl_mac_bytes_to_string(request.mobile_mac_addr_bytes) ;
const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ;
free(mac_mobile) ;
current_request->set_mobile(&mobile) ;
// Timestamp
current_request->set_time_sent(Timestamp(request.request_time)) ;
// Read {MAC_AP;SS} mcouples (request_info)
unordered_map<string, Measurement> measurements ;
owl_request_info request_info ;
char *mac_ap ;
for (int i = 0 ; i < request.nb_info ; ++i)
{
nread = recvfrom(sockfd, &request_info, sizeof(request_info), 0,
(struct sockaddr *) &client, &client_len) ;
if (nread <= 0)
{
cerr << "No request info received!" << endl ;
current_request->clear() ;
return *current_request ;
}
mac_ap = owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes) ;
const AccessPoint &ap = Stock::find_create_ap(mac_ap) ;
measurements[mac_ap].set_ap(&ap) ;
measurements[mac_ap].add_ss(static_cast<int_fast8_t>
(request_info.antenna_signal_dbm)) ;
free(mac_ap) ;
}
current_request->set_measurements(measurements) ;
return *current_request ;
}

View File

@ -0,0 +1,56 @@
#ifndef _OWLPS_POSITIONING_INPUTUDPSOCKET_HH_
#define _OWLPS_POSITIONING_INPUTUDPSOCKET_HH_
#include "inputmedium.hh"
/// Receives \link Request requests \endlink from a UDP socket
class InputUDPSocket: public InputMedium
{
protected:
int sockfd ;
uint_fast16_t listening_port ;
/** @name Operations */
//@{
/// Initialises the socket
bool init_socket(void) ;
//@}
public:
InputUDPSocket(const uint_fast16_t _port) ;
~InputUDPSocket(void) ;
/** @name Read accessors */
//@{
/// Always false
bool eof(void) const ;
//@}
/** @name Operations */
//@{
/// Reads the next request
const Request& get_next_request(void) ;
/// Closes the socket
bool close_socket(void) ;
//@}
} ;
/* *** Read accessors *** */
/**
* Note that by definition, the end of a socket is never reached.
* @return \em true if the socket is closed.
* @return \em false if the socket is opened.
*/
inline bool InputUDPSocket::eof() const
{
return sockfd < 0 ;
}
#endif // _OWLPS_POSITIONING_INPUTUDPSOCKET_HH_

View File

@ -145,9 +145,11 @@ void UserInterface::fill_input_options()
options.add_options()
("input.medium,I", po::value<string>(),
"Medium from which requests are read. Allowed: CSV.")
"Medium from which requests are read. Allowed: CSV, UDP.")
("input.csv-file,C", po::value<string>(),
"CSV file to use for input (when input.medium = CSV).")
("input.udp-port,p", po::value<int>(),
"Port on which the UDP socket listens (when input.medium = UDP).")
;
file_options->add(options) ;