[Positioning] Add Configuration and UserInterface

- Add class Configuration, a stock for the configuration structure.
- Add class UserInterface, that handles the configuration input.
- Update owlps-positioning.cc (delete old stuff like configuration) and
  delete owlps-positioning.hh: we now have a compilable executable.
This commit is contained in:
Matteo Cypriani 2010-02-11 09:46:40 +01:00
parent 12d14b805f
commit 9cf4daca3b
13 changed files with 367 additions and 84 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*~
*.o
*.swp
*.orig

View File

@ -2,3 +2,4 @@ doc
csv/*.csv
tests/*.cc
tests/tests
owlps-positioning

View File

@ -17,7 +17,7 @@ RM_RECURSIVE = \rm -fr
CP = cp -v
# Autres outils
STYLE = astyle --style=gnu
STYLE = astyle --style=gnu --formatted
CPPCHECK = cppcheck --enable=all
DOXYGEN = doxygen
@ -26,20 +26,20 @@ GXX = g++-4.4
TESTSGXXFLAGS = -I$(TEST_DIR) -I.
GXXFLAGS = $(DEBUG) -Wall -Wextra $(STLPORTGXXFLAGS)
LD = $(GXX)
LDFLAGS = -lm -lrt
LIBS = -lpq -lboost_program_options-mt
LDFLAGS = -lm -lrt -lboost_program_options
#LIBS = -lpq
TARGET = owlps-positioning
#HEADER = owlps-positioning.hh
OBJ = posutil.o stock.o timestamp.o point3d.o referencepoint.o \
waypoint.o building.o area.o wifidevice.o accesspoint.o \
mobile.o measurement.o calibrationmeasurement.o request.o \
inputcsv.o
inputcsv.o configuration.o userinterface.o
all: $(TARGET)
%: %.o
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
$(LD) $(LDFLAGS) -o $@ $^
%.o: %.cc $(HEADER)
$(GXX) $(GXXFLAGS) -c $<
@ -49,6 +49,8 @@ $(TEST_DIR)/%_test.o: %.o
posutil.o: posutil.hh
stock.o: stock.hh
configuration.o: configuration.hh
userinterface.o: userinterface.hh configuration.o
timestamp.o: timestamp.hh
point3d.o: point3d.hh
referencepoint.o : referencepoint.hh point3d.o

View File

@ -4,6 +4,11 @@
utilisant les champs de direction.
° Lire la direction en tant qu'entier plutôt que float ?
- Tests unitaires
Écrire une classe utilitaire pour les tests contenant par exemple
une fonction pour écrire un fichier de test à partir d'un
vector<string>.
- Réorganisation du dépôt ?
owlps-positioning/src
owlps-positioning/include

View File

@ -0,0 +1,40 @@
#include "configuration.hh"
namespace po = boost::program_options ;
/* *** Attribute definitions *** */
po::variables_map Configuration::configuration ;
/* *** Read accessors *** */
po::variables_map& Configuration::getw_configuration()
{
return configuration ;
}
bool Configuration::is_configured(const std::string &key)
{
if (configuration.count(key))
return true ;
return false ;
}
const std::string&
Configuration::get_string_value(const std::string &key)
{
return configuration[key].as<std::string>() ;
}
int Configuration::get_int_value(const std::string &key)
{
return configuration[key].as<int>() ;
}

View File

@ -0,0 +1,26 @@
#ifndef _OWLPS_POSITIONING_CONFIGURATION_HH_
#define _OWLPS_POSITIONING_CONFIGURATION_HH_
#include <string>
#include <boost/program_options/variables_map.hpp>
/// Stocks the configuration of the program
class Configuration
{
private:
/// Configuration structure
static boost::program_options::variables_map configuration ;
public:
/// Get a reference to the configuration structure
static boost::program_options::variables_map& getw_configuration(void) ;
/// Checks if the key exists in the configuration
static bool is_configured(const std::string &key) ;
/// Get the string value corresponding to \em key
static const std::string& get_string_value(const std::string &key) ;
/// Get the int value corresponding to \em key
static int get_int_value(const std::string &key) ;
} ;
#endif // _OWLPS_POSITIONING_CONFIGURATION_HH_

View File

@ -1,64 +1,10 @@
#include "owlps-positioning.hh"
#include "userinterface.hh"
int main(int argc, char** argv)
int main(int argc, char **argv)
{
string config_filename = DEFAULT_CONFIG_FILE;
int port, mport;
UserInterface *ui = new UserInterface(argc, argv) ;
delete ui ; // We don't need it any more
/* Options spécifiques à la ligne de commandes */
po::options_description generic("Options générales ");
generic.add_options()
("help,h", "Affichage de l'aide")
("config-file,f", po::value<string>(), "Fichier de configuration")
("input-topo,T", po::value<string>(), "Input file topology")
("input-waypoint,W", po::value<string>(), "Input file waypoint")
("input-refpoint,R", po::value<string>(), "Input file reference point")
("input-ap,A", po::value<string>(), "Input file accesspoint")
;
/* Options ligne de commandes & fichier de configuration */
po::options_description config("Paramètres ");
config.add_options()
("server.port,l", po::value<int>(&port) -> default_value(9902), "Port d'écoute du serveur")
("server.mobile-port,p", po::value<int>(&mport) -> default_value(9903), "Port d'envoi vers le mobile")
("db.name,D", po::value<string>(), "Nom de la base de données à utiliser")
("db.host,H", po::value<string>(), "Adresse de l'hôte hébergeant la base de données")
("db.user,U", po::value<string>(), "Nom de l'utilisateur pour la connexion à la base de données")
("db.passwd,P", po::value<string>(), "Mot de passe pour la connexion à la base de données")
;
/* Total des options acceptées en ligne de commandes */
po::options_description cmd_line_options("Options acceptées ") ;
cmd_line_options.add(generic).add(config) ;
/* Parcours de la ligne de commandes */
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, cmd_line_options), vm) ;
if (vm.count("help")) // L'utilisateur a demandé l'aide
{
cout << cmd_line_options << endl ;
return 0 ;
}
if (vm.count("config-file")) // L'utilisateur a spécifié un fichier de config
config_filename = vm["config-file"].as<string>() ;
ifstream ifs(config_filename.c_str());
if (!ifs.is_open())
cerr << "Attention ! Erreur lors de l'ouverture du fichier de configuration « " << config_filename << " » : le fichier n'existe pas ou ne peut être lu.\nUtilisation des valeurs par défaut..." << endl ;
else // Parcours du fichier de config
po::store(po::parse_config_file(ifs, config), vm) ;
po::notify(vm);
Server server(port, mport);
if (server.init(vm))
return 1 ;
server.start();
return 0;
return 0 ;
}

View File

@ -1,14 +0,0 @@
#ifndef _OWLPS_HH_
#define _OWLPS_HH_
#include <iostream>
#include <cstdio>
#include <boost/program_options.hpp>
#include "server.hh"
//using namespace std ;
//namespace po = boost::program_options ;
#endif // _OWLPS_HH_

View File

@ -7,13 +7,11 @@ using std::tr1::unordered_map ;
/* *** Attribute definition *** */
/* *** Attribute definitions *** */
unordered_map<string, Mobile> Stock::mobiles =
unordered_map<string, Mobile>() ;
unordered_map<string, Mobile> Stock::mobiles ;
unordered_map<string, AccessPoint> Stock::aps =
unordered_map<string, AccessPoint>() ;
unordered_map<string, AccessPoint> Stock::aps ;

View File

@ -0,0 +1,22 @@
#include <cxxtest/TestSuite.h>
#include "configuration.hh"
class Configuration_test: public CxxTest::TestSuite
{
public:
void test_accessors(void)
{
// Non-configured values
TS_ASSERT(! Configuration::is_configured("miaou")) ;
TS_ASSERT(! Configuration::is_configured("ouaf")) ;
/*
* Due to the lack of direct variables_map manipulators, it is
* hard to manually add values in order to test them.
* Some other tests are done in userinterface_test.hh.
*/
}
} ;

View File

@ -0,0 +1,88 @@
#include <cxxtest/TestSuite.h>
#include "userinterface.hh"
#include <string>
#include <fstream>
class UserInterface_test: public CxxTest::TestSuite
{
private:
std::string config_file_name ;
std::vector<std::string> config_lines ; // Test config file contents
public:
UserInterface_test(void)
{
// If we cannot open the file, we want to stop the test
CxxTest::setAbortTestOnFail(true) ;
// Filling name and contents of the config test file
config_file_name = "/tmp/UserInterface_test_config_file.csv" ;
config_lines.push_back("\n") ;
config_lines.push_back("[server]\n") ;
config_lines.push_back("\n") ;
config_lines.push_back("port = 42\n") ;
config_lines.push_back("\n") ;
// Opening the file
std::ofstream config_file ;
config_file.open(config_file_name.c_str()) ;
if (! config_file)
TS_FAIL("Cannot open test config file for creation!") ;
// Writing contents to the file
for (std::vector<std::string>::const_iterator i = config_lines.begin() ;
i != config_lines.end() ; ++i)
config_file << *i ;
config_file.close() ;
// Back to the normal behaviour (i.e. do not abort on fail)
CxxTest::setAbortTestOnFail(false) ;
}
~UserInterface_test(void)
{
// Deleting the test config file
if (remove(config_file_name.c_str()) == -1)
TS_WARN("Cannot remove test config file!") ;
}
static UserInterface_test* createSuite(void)
{
return new UserInterface_test() ;
}
static void destroySuite(UserInterface_test *suite)
{
delete suite ;
}
void test_constructors(void)
{
// Note: as --help makes the program exit, we cannot test it.
const char *argv[] =
{
"owlps-positioning", // program name
"--config-file",
config_file_name.c_str()
} ;
int argc = 3 ;
UserInterface ui(argc, const_cast<char**>(argv)) ;
TS_ASSERT(Configuration::is_configured("server.port")) ;
TS_ASSERT(Configuration::is_configured("config-file")) ;
TS_ASSERT_EQUALS(Configuration::get_int_value("server.port"), 42) ;
TS_ASSERT_EQUALS(Configuration::get_string_value("config-file"),
config_file_name) ;
}
} ;

View File

@ -0,0 +1,128 @@
#include "userinterface.hh"
#include "configuration.hh"
#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
using namespace std ;
namespace po = boost::program_options ;
/* *** Default value definitions *** */
#define DEFAULT_CONFIG_FILE_NAME "cfg/owlps-positioning.cfg"
#define DEFAULT_LISTENING_PORT 9902
/* *** Constructors *** */
UserInterface::UserInterface(const int argc, char **argv)
{
cli_argument_count = argc ;
cli_argument_values = argv ;
config_file_name = DEFAULT_CONFIG_FILE_NAME ;
cli_options = new po::options_description("General options") ;
file_options = new po::options_description("Parameters") ;
fill_options() ;
parse_options() ;
}
UserInterface::~UserInterface()
{
delete cli_options ;
delete file_options ;
}
/* *** Operations *** */
void UserInterface::fill_options()
{
fill_cli_options() ;
fill_file_options() ;
// File options are also accepted on the command line
cli_options->add(*file_options) ;
}
void UserInterface::fill_cli_options()
{
cli_options->add_options()
("help,h", "Print help")
("config-file,f", po::value<string>(),
"Alternative configuration file")
;
}
void UserInterface::fill_file_options()
{
file_options->add_options()
("server.port,l", po::value<int>()
->default_value(DEFAULT_LISTENING_PORT),
"Server listening port")
;
}
void UserInterface::parse_options()
{
parse_command_line() ;
print_usage_and_exit_if_requested() ;
// Was the config file name specified on the command line?
if (Configuration::is_configured("config-file"))
config_file_name = Configuration::get_string_value("config-file") ;
parse_file() ;
po::notify(Configuration::getw_configuration()) ;
}
void UserInterface::parse_command_line() const
{
po::store(po::parse_command_line(cli_argument_count,
cli_argument_values,
*cli_options),
Configuration::getw_configuration()) ;
}
void UserInterface::print_usage_and_exit_if_requested() const
{
if (Configuration::is_configured("help"))
{
cout << *cli_options ;
exit(0) ;
}
}
void UserInterface::parse_file() const
{
ifstream config_file(config_file_name.c_str()) ;
if (! config_file)
{
cerr
<< "Warning! Error opening input configuration file « "
<< config_file_name
<< " »! Using command line and default values…"
<< endl ;
return ;
}
po::store(po::parse_config_file(config_file, *file_options),
Configuration::getw_configuration()) ;
}

View File

@ -0,0 +1,40 @@
#ifndef _OWLPS_POSITIONING_USERINTERFACE_HH_
#define _OWLPS_POSITIONING_USERINTERFACE_HH_
#include <string>
#include <boost/program_options/options_description.hpp>
/// Handles configuration inputs from user
class UserInterface
{
protected:
std::string config_file_name ;
int cli_argument_count ;
char **cli_argument_values ;
boost::program_options::options_description *cli_options ;
boost::program_options::options_description *file_options ;
/** @name Operations */
//@{
/// Fill in all the options
void fill_options(void) ;
/// Fill in the options accepted on the command line
void fill_cli_options(void) ;
/// \brief Fill in the options accepted on the command line and in
/// the configuration file
void fill_file_options(void) ;
/// Parse all the configuration inputs and updates Configuration
void parse_options(void) ;
void parse_command_line(void) const ;
void parse_file(void) const ;
/// If help was requested by user, displays accepted options and exit
void print_usage_and_exit_if_requested(void) const ;
//@}
public:
UserInterface(const int argc, char **argv) ;
~UserInterface(void) ;
} ;
#endif // _OWLPS_POSITIONING_USERINTERFACE_HH_