[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:
parent
c3c319a7f1
commit
161157dae7
4
Makefile
4
Makefile
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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!") ;
|
||||
|
|
|
@ -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 ;
|
||||
}
|
|
@ -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_
|
|
@ -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) ;
|
||||
|
|
Loading…
Reference in New Issue