[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 $@
|
@make -C $@
|
||||||
owlps-aggregator: libowlps
|
owlps-aggregator: libowlps
|
||||||
@make -C $@
|
@make -C $@
|
||||||
owlps-positioning:
|
owlps-positioning: libowlps
|
||||||
@make -C $@
|
@make -C $@
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ install-owlps-listener: install-libowlps
|
||||||
@make -C $(subst install-,,$@) install
|
@make -C $(subst install-,,$@) install
|
||||||
install-owlps-aggregator: install-libowlps
|
install-owlps-aggregator: install-libowlps
|
||||||
@make -C $(subst install-,,$@) install
|
@make -C $(subst install-,,$@) install
|
||||||
install-owlps-positioning:
|
install-owlps-positioning: install-libowlps
|
||||||
@make -C $(subst install-,,$@) install
|
@make -C $(subst install-,,$@) install
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,16 +22,20 @@ STYLE = astyle --style=gnu --formatted
|
||||||
CPPCHECK = cppcheck --enable=all
|
CPPCHECK = cppcheck --enable=all
|
||||||
DOXYGEN = doxygen >/dev/null
|
DOXYGEN = doxygen >/dev/null
|
||||||
|
|
||||||
# Compilation tools and flags
|
# Compilation tools
|
||||||
COLORGCC := $(shell which colorgcc >/dev/null 2>&1 ; echo $$?)
|
COLORGCC := $(shell which colorgcc >/dev/null 2>&1 ; echo $$?)
|
||||||
ifeq ($(COLORGCC), 0)
|
ifeq ($(COLORGCC), 0)
|
||||||
CXX = colorgcc
|
CXX = colorgcc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Flags
|
||||||
|
LIBOWLPS_DIR = ../libowlps
|
||||||
#DEBUG = -g
|
#DEBUG = -g
|
||||||
TESTSGXXFLAGS = -I$(TESTS_DIR) -I$(SRC_DIR) -I.
|
TESTSGXXFLAGS = -I$(TESTS_DIR) -I$(SRC_DIR) -I.
|
||||||
GXXFLAGS = $(DEBUG) -Wall -Wextra
|
GXXFLAGS = $(DEBUG) -Wall -Wextra -I$(LIBOWLPS_DIR)
|
||||||
LD = $(CXX)
|
LD = $(CXX)
|
||||||
LDFLAGS = -lstdc++ -lm -lrt -lboost_program_options
|
LDFLAGS = -lstdc++ -lm -lrt -lboost_program_options \
|
||||||
|
-L$(LIBOWLPS_DIR) -lowlps
|
||||||
|
|
||||||
# Targets
|
# Targets
|
||||||
TARGET = owlps-positioning
|
TARGET = owlps-positioning
|
||||||
|
@ -75,6 +79,7 @@ OBJ_LIST = \
|
||||||
positioning.o \
|
positioning.o \
|
||||||
input.o \
|
input.o \
|
||||||
inputcsv.o \
|
inputcsv.o \
|
||||||
|
inputudpsocket.o \
|
||||||
inputlogcsv.o
|
inputlogcsv.o
|
||||||
OBJ_NOTEST_LIST = \
|
OBJ_NOTEST_LIST = \
|
||||||
posexcept.o \
|
posexcept.o \
|
||||||
|
@ -184,11 +189,18 @@ $(OBJ_DIR)/inputcsv.o: \
|
||||||
$(OBJ_DIR)/request.o \
|
$(OBJ_DIR)/request.o \
|
||||||
$(OBJ_DIR)/calibrationrequest.o \
|
$(OBJ_DIR)/calibrationrequest.o \
|
||||||
$(OBJ_DIR)/stock.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: \
|
$(OBJ_DIR)/inputlogcsv.o: \
|
||||||
$(SRC_DIR)/inputlogmedium.hh \
|
$(SRC_DIR)/inputlogmedium.hh \
|
||||||
$(OBJ_DIR)/request.o
|
$(OBJ_DIR)/request.o
|
||||||
$(OBJ_DIR)/input.o: \
|
$(OBJ_DIR)/input.o: \
|
||||||
$(OBJ_DIR)/inputcsv.o \
|
$(OBJ_DIR)/inputcsv.o \
|
||||||
|
$(OBJ_DIR)/inputudpsocket.o \
|
||||||
$(OBJ_DIR)/inputlogcsv.o \
|
$(OBJ_DIR)/inputlogcsv.o \
|
||||||
$(OBJ_DIR)/calibrationrequest.o \
|
$(OBJ_DIR)/calibrationrequest.o \
|
||||||
$(OBJ_DIR)/configuration.o \
|
$(OBJ_DIR)/configuration.o \
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "input.hh"
|
#include "input.hh"
|
||||||
#include "inputcsv.hh"
|
#include "inputcsv.hh"
|
||||||
|
#include "inputudpsocket.hh"
|
||||||
#include "inputlogcsv.hh"
|
#include "inputlogcsv.hh"
|
||||||
#include "calibrationrequest.hh"
|
#include "calibrationrequest.hh"
|
||||||
#include "configuration.hh"
|
#include "configuration.hh"
|
||||||
|
@ -56,6 +57,15 @@ void Input::initialise_input_medium()
|
||||||
InputCSV(Configuration::string_value("input.csv-file")) ;
|
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
|
else
|
||||||
throw bad_configuration(
|
throw bad_configuration(
|
||||||
"The specified input medium « "+ medium_name +" » is unknown!") ;
|
"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()
|
options.add_options()
|
||||||
("input.medium,I", po::value<string>(),
|
("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>(),
|
("input.csv-file,C", po::value<string>(),
|
||||||
"CSV file to use for input (when input.medium = CSV).")
|
"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) ;
|
file_options->add(options) ;
|
||||||
|
|
Loading…
Reference in New Issue