Merge branch 'dev' into dev-drone
Update string2data() to the new CSV format (and clean it a bit).
This commit is contained in:
commit
b62987efb0
65
TODO
65
TODO
|
@ -68,4 +68,67 @@
|
|||
|
||||
* Positioning
|
||||
|
||||
- Has its own fat TODO file, which I could merge in here.
|
||||
- Known bugs
|
||||
° Cannot compute the error (Real) with autocalibration requests.
|
||||
|
||||
- Algorithms
|
||||
° MinMax: use a different step for X, Y and Z?
|
||||
|
||||
- Autocalibration
|
||||
° Generate reference points in 3D.
|
||||
° Handle 2 APs, not only >2 APs.
|
||||
° Find why some CalibrationRequest were not deleted when
|
||||
calling Stock::delete_calibration_request() (via
|
||||
ReferencePoint::delete_requests()).
|
||||
|
||||
- Refactoring
|
||||
° Split Stock::generate_reference_point() into several functions.
|
||||
° Write a class for Request::type?
|
||||
CalibrationRequest::direction uses a dedicated class Direction, why
|
||||
not Request::type? That would simplify writing of the type to
|
||||
streams (no need to cast each time anymore).
|
||||
° Wi-Fi devices' list
|
||||
. Merge Stock::mobiles & Stock::aps?
|
||||
. Factorise AccessPointsReaderCSV & MobilesReaderCSV?
|
||||
° Members renaming
|
||||
. InputMedium:
|
||||
. - current_line_nb & get_current_line_nb()
|
||||
. - get_next_request() −> read_next_request()
|
||||
. Input: get_next_request() −> read_next_request()
|
||||
. Area: p_min et p_max −> coord_min et coord_max
|
||||
|
||||
- User interface
|
||||
° When reading the APs, add them to the mobiles' list (or another
|
||||
way to be able to have a single entry for an AP).
|
||||
° Review the option names & descriptions.
|
||||
° Add option positioning.self-calibrate (or autocalibrate), to
|
||||
activate automatically the options needed by the autocalibration.
|
||||
° Improve --verbose (and/or debug level): print the options, etc.
|
||||
° Case-insensitive string comparison (for algorithm names, etc.).
|
||||
° Use a prefix for configuration files (search for config files set
|
||||
with relative path in owlps-positioning.cfg in the same directory).
|
||||
|
||||
- Optimisation & code improvement
|
||||
° Multithread algorithm calls.
|
||||
° ReferencePoint: the request list should be an unordered_set
|
||||
instead of a vector, to guarantee the unicity of the elements.
|
||||
° Pre-allocate vectors' memory with reserve().
|
||||
"C++ en action", p. 217.
|
||||
° Copy of containers to streams (in some operator<<() for
|
||||
instance).
|
||||
"C++ en action", p. 275.
|
||||
° Review all the classes to respect principles exposed in "Coder
|
||||
proprement", chapter 6, p. 103: do implement accessors for each
|
||||
class attribute, etc.
|
||||
|
||||
- Unit tests
|
||||
° Update tests (currently unmaintained).
|
||||
° Unfinished tests:
|
||||
. InputDataReader
|
||||
. Input
|
||||
. Output
|
||||
. Positioning
|
||||
° Test InterlinkNetworks::compute() ?
|
||||
° Timestamp: there is a probability of 10^-6 that the value in
|
||||
nanoseconds and the rounded value in milliseconds are identical, in
|
||||
which case some tests can fail.
|
||||
|
|
|
@ -66,3 +66,8 @@ purge : clean
|
|||
|
||||
help :
|
||||
@make help
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -67,3 +67,8 @@ purge : clean
|
|||
|
||||
help :
|
||||
@make help
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -121,3 +121,8 @@ purge : clean
|
|||
|
||||
help :
|
||||
@make help
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -123,3 +123,8 @@ purge : clean
|
|||
|
||||
help :
|
||||
@make help
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -157,83 +157,6 @@ typedef struct _owl_autocalibration_order
|
|||
#define OWL_80211_HZ_CHANNEL_14 2477000000ul
|
||||
|
||||
|
||||
|
||||
/* Packet header sizes (in bytes) */
|
||||
#define IEEE80211_HEADER_SIZE_DATA 24 // Header size for a Data frame
|
||||
#define LLC_HEADER_SIZE 8
|
||||
|
||||
/* IEEE 802.11 frame types */
|
||||
// Beacon (TODO: convert to mask)
|
||||
#define RAW_PACKET_TYPE_BEACON 0x80
|
||||
|
||||
// Data frame
|
||||
#define FRAME_TYPE_DATA_MASK 0x08
|
||||
#define IS_DATA_FRAME(FC1) \
|
||||
(((FC1) & FRAME_TYPE_DATA_MASK) == FRAME_TYPE_DATA_MASK)
|
||||
|
||||
// QoS Data frame
|
||||
#define FRAME_SUBTYPE_QOS_MASK 0x80
|
||||
#define DATA_FRAME_IS_QOS(FC1) \
|
||||
(((FC1) & FRAME_SUBTYPE_QOS_MASK) == FRAME_SUBTYPE_QOS_MASK)
|
||||
|
||||
// To/From DS
|
||||
#define FRAME_FROM_STA_MASK 0x02
|
||||
#define IS_FRAME_FROM_STA(FC2) \
|
||||
(((FC2) & FRAME_FROM_STA_MASK) != FRAME_FROM_STA_MASK)
|
||||
|
||||
|
||||
/* Positions of the radiotap header fixed fields (in bytes) */
|
||||
#define RTAP_P_HREVISION 0 // Header revision
|
||||
#define RTAP_P_HPAD 1 // Header pad
|
||||
#define RTAP_P_HLENGTH 2 // Header length
|
||||
#define RTAP_P_PRESENTFLAGS 4 // Present flags
|
||||
|
||||
|
||||
/* Radiotap field lengths (in bytes) */
|
||||
#define RTAP_L_HREVISION 1 // Header revision
|
||||
#define RTAP_L_HPAD 1 // Header pad
|
||||
#define RTAP_L_HLENGTH 2 // Header length
|
||||
#define RTAP_L_PRESENTFLAGS 4 // Present flags
|
||||
#define RTAP_L_MACTS 8 // MAC timestamp (Time Synchronization Function Timer)
|
||||
#define RTAP_L_FLAGS 1 // autre champ de flags
|
||||
#define RTAP_L_RATE 1 // Data rate
|
||||
#define RTAP_L_CHANNEL 2 // Channel frequency
|
||||
#define RTAP_L_CHANNELTYPE 2 // Channel type
|
||||
#define RTAP_L_ANTENNASIGNALDBM 1 // SSI signal (dBm)
|
||||
#define RTAP_L_ANTENNANOISEDBM 1 // SSI noise (dBm)
|
||||
#define RTAP_L_ANTENNA 1 // Antenna number
|
||||
#define RTAP_L_FHSS 2 // Hop set and pattern for Frequency-Hopping Spread Spectrum
|
||||
#define RTAP_L_LOCKQUALITY 2 // Signal quality
|
||||
#define RTAP_L_TXATTENUATION 2 // Transmit power from max power
|
||||
#define RTAP_L_TXATTENUATIONDB 2 // Idem (dB)
|
||||
#define RTAP_L_TXATTENUATIONDBM 1 // Idem (dBm)
|
||||
#define RTAP_L_ANTENNASIGNALDB 1 // SSI signal (dB)
|
||||
#define RTAP_L_ANTENNANOISEDB 1 // SSI noise (dB)
|
||||
#define RTAP_L_FCS 4 // Frame Check Sequence
|
||||
//#define RTAP_L_CHANNELP // Extended channel info (not implemented)
|
||||
//#define RTAP_L_EXT // Extension aux Present flags (not emplemented)
|
||||
|
||||
|
||||
/* Positions in 'Present flags' (and present fields 'check' array) */
|
||||
#define RTAP_MACTS 0
|
||||
#define RTAP_FLAGS 1
|
||||
#define RTAP_RATE 2
|
||||
#define RTAP_CHANNEL 3 // and RTAP_CHANNELTYPE
|
||||
#define RTAP_FHSS 4
|
||||
#define RTAP_ANTENNASIGNALDBM 5
|
||||
#define RTAP_ANTENNANOISEDBM 6
|
||||
#define RTAP_LOCKQUALITY 7
|
||||
#define RTAP_TXATTENUATION 8
|
||||
#define RTAP_TXATTENUATIONDB 9
|
||||
#define RTAP_TXATTENUATIONDBM 10
|
||||
#define RTAP_ANTENNA 11
|
||||
#define RTAP_ANTENNASIGNALDB 12
|
||||
#define RTAP_ANTENNANOISEDB 13
|
||||
#define RTAP_FCS 14
|
||||
//#define RTAP_CHANNELP 18
|
||||
//#define RTAP_EXT 31
|
||||
|
||||
|
||||
/* Misc. */
|
||||
// Length of a MAC address in string format (including '\0')
|
||||
#define OWL_ETHER_ADDR_STRLEN 18
|
||||
|
@ -245,10 +168,6 @@ extern owl_bool owl_run ;
|
|||
|
||||
|
||||
/* Function error codes */
|
||||
#define ERR_SETTING_MODE 101
|
||||
#define ERR_SETTING_CHANNEL 102
|
||||
#define ERR_READING_CHANNEL 103
|
||||
#define ERR_READING_MODE 104
|
||||
#define ERR_BAD_SIGNAL 111
|
||||
|
||||
|
||||
|
|
|
@ -605,7 +605,7 @@ void* monitor_requests(void *NULL_value)
|
|||
request_info_ptr = request_ptr->info ;
|
||||
while (request_info_ptr != NULL)
|
||||
{
|
||||
request.nb_info++;
|
||||
++request.nb_info ;
|
||||
request_info_ptr = request_info_ptr->next ;
|
||||
}
|
||||
// Endianess conversions:
|
||||
|
|
|
@ -798,28 +798,29 @@ void* receive_position(void* NULL_value)
|
|||
}
|
||||
|
||||
|
||||
/* Split the string received from OwlPS Positioning and store the fields
|
||||
* in a result structure.
|
||||
*
|
||||
* Handled CSV format:
|
||||
* Mobile_MAC;Request_type;Request_timestamp;Algorithm;X;Y;Z;Error;Area
|
||||
* The Request_timestamp format is: seconds.nanoseconds
|
||||
*/
|
||||
void string2data(char* string_data)
|
||||
{
|
||||
/*Découpage de la chaine de caractère reçu du serveur de positionnement
|
||||
sous forme de addrMAC;TypeRequete;Timestamp1.Timestamp2;Algo;X;Y;Z
|
||||
en variables séparées
|
||||
*/
|
||||
|
||||
char *mac = NULL ;
|
||||
char *ptr = NULL ;
|
||||
|
||||
char *delims = ";" ;
|
||||
const char delims[] = ";" ;
|
||||
|
||||
int type_req = 0 ;
|
||||
int count_algo= 0 ;
|
||||
int count_print = 0 ;
|
||||
int onetime = 0 ;
|
||||
int error = 0 ;
|
||||
owl_bool error_present = FALSE ;
|
||||
|
||||
while(onetime<1)
|
||||
{
|
||||
|
||||
//Lecture Adresse Mac
|
||||
// Mobile MAC address
|
||||
ptr = strtok(string_data, delims) ;
|
||||
if(ptr==NULL)
|
||||
{
|
||||
|
@ -828,7 +829,7 @@ void string2data(char* string_data)
|
|||
}
|
||||
mac = ptr ;
|
||||
|
||||
//Lecture Type Request
|
||||
// Request type
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if (ptr==NULL)
|
||||
{
|
||||
|
@ -837,7 +838,7 @@ void string2data(char* string_data)
|
|||
}
|
||||
type_req = atoi(ptr) ;
|
||||
|
||||
//Lecture TimeStamp1
|
||||
// Timestamp (seconds)
|
||||
ptr = strtok(NULL, ".") ;
|
||||
if (ptr==NULL)
|
||||
{
|
||||
|
@ -846,7 +847,7 @@ void string2data(char* string_data)
|
|||
}
|
||||
sscanf(ptr, "%ld", ×tamp.tv_sec) ;
|
||||
|
||||
//Lecture TimeStamp2
|
||||
// Timestamp (nanoseconds)
|
||||
ptr = strtok(NULL, ";") ;
|
||||
if (ptr==NULL)
|
||||
{
|
||||
|
@ -860,14 +861,15 @@ void string2data(char* string_data)
|
|||
|
||||
while(run)
|
||||
{
|
||||
//Lecture de l'algorythme utilisé
|
||||
// Algorithm name
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if(ptr==NULL) break ;
|
||||
sscanf(ptr, "%s", results[count_algo].algo) ;
|
||||
if (ptr == NULL)
|
||||
break ;
|
||||
strncpy(results[count_algo].algo, ptr, ALGO_STRLEN) ;
|
||||
if(!strcmp(results[count_algo].algo,"Real"))
|
||||
error=1;
|
||||
error_present = TRUE ;
|
||||
|
||||
//Lecture du point X
|
||||
// X coordinate
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if(ptr==NULL)
|
||||
{
|
||||
|
@ -885,7 +887,7 @@ void string2data(char* string_data)
|
|||
}
|
||||
results[count_algo].x = atof(ptr) ;
|
||||
|
||||
//Lecture du point Y
|
||||
// Y coordinate
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if(ptr==NULL)
|
||||
{
|
||||
|
@ -903,7 +905,7 @@ void string2data(char* string_data)
|
|||
}
|
||||
results[count_algo].y = atof(ptr) ;
|
||||
|
||||
//Lecture du point Z
|
||||
// Z coordinate
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if(ptr==NULL)
|
||||
{
|
||||
|
@ -914,15 +916,16 @@ void string2data(char* string_data)
|
|||
}
|
||||
else
|
||||
{
|
||||
perror ("algo");
|
||||
print_error("algo") ;
|
||||
count_algo--;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
results[count_algo].z = atof(ptr) ;
|
||||
if(error==1)
|
||||
|
||||
// Distance error
|
||||
if (error_present)
|
||||
{
|
||||
//Lecture du message Error
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if(ptr==NULL)
|
||||
{
|
||||
|
@ -938,52 +941,50 @@ void string2data(char* string_data)
|
|||
break ;
|
||||
}
|
||||
}
|
||||
results[count_algo].check = ptr ;
|
||||
|
||||
//Lecture valeur Error
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if(ptr==NULL)
|
||||
{
|
||||
if(count_algo==0)
|
||||
{
|
||||
print_error ("trame");
|
||||
break ;
|
||||
}
|
||||
else
|
||||
{
|
||||
perror ("algo");
|
||||
count_algo--;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
results[count_algo].err = atof(ptr) ;
|
||||
|
||||
|
||||
++count_algo ;
|
||||
results[count_algo].error = atof(ptr) ;
|
||||
}
|
||||
++count_algo ;
|
||||
|
||||
else
|
||||
++count_algo ;
|
||||
// Area name
|
||||
ptr = strtok(NULL, delims) ;
|
||||
if (ptr == NULL)
|
||||
{
|
||||
if (count_algo == 0)
|
||||
{
|
||||
print_error("trame") ;
|
||||
break ;
|
||||
}
|
||||
else
|
||||
{
|
||||
print_error("algo") ;
|
||||
count_algo-- ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
strncpy(results[count_algo].area, ptr, AREA_STRLEN) ;
|
||||
}
|
||||
|
||||
for (count_print = 0 ; count_print < count_algo ; ++count_print)
|
||||
printf("\n----------------\n"
|
||||
" Adresse Mac : %s\n"
|
||||
" Type de requete : %d\n"
|
||||
" Timestamp : %ld.%ld\n"
|
||||
" Algo : %s\n"
|
||||
" X : %f\n "
|
||||
" Y : %f\n"
|
||||
" Z : %f\n"
|
||||
" Mobile's MAC address: %s\n"
|
||||
" Request type: %d\n"
|
||||
" Timestamp: %ld.%ld\n"
|
||||
" Algorithm: %s\n"
|
||||
" X: %f\n"
|
||||
" Y: %f\n"
|
||||
" Z: %f\n"
|
||||
" Distance error: %f\n"
|
||||
" Area: %s\n"
|
||||
"------------------\n",
|
||||
mac,
|
||||
type_req,
|
||||
timestamp.tv_sec,
|
||||
timestamp.tv_nsec,
|
||||
timestamp.tv_sec, timestamp.tv_nsec,
|
||||
results[count_print].algo,
|
||||
results[count_print].x,
|
||||
results[count_print].y,
|
||||
results[count_print].z) ;
|
||||
results[count_print].z,
|
||||
results[count_print].error,
|
||||
results[count_print].area) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
#define DEFAULT_DELAY_CALIB 50000 // Calibration request
|
||||
#define DEFAULT_DELAY_NORMAL 25000 // Localisation request
|
||||
|
||||
/* Maximum length of the algorithm name */
|
||||
/* Maximum length of the algorithm & area names */
|
||||
#define ALGO_STRLEN 15
|
||||
#define AREA_STRLEN 50
|
||||
|
||||
/* GPS inputs */
|
||||
#define SEPARATOR ','
|
||||
|
@ -38,15 +39,15 @@
|
|||
#define ERR_BAD_USAGE 1 // Bad program call (bad number of arguments)
|
||||
|
||||
|
||||
/* Received result */
|
||||
/* Result from OwlPS Positioning (parsed string structure) */
|
||||
typedef struct _result
|
||||
{
|
||||
char algo[ALGO_STRLEN];
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
char *check;
|
||||
float err;
|
||||
float error ;
|
||||
char area[AREA_STRLEN] ;
|
||||
} result ;
|
||||
|
||||
typedef struct _gps
|
||||
|
|
|
@ -99,3 +99,8 @@ purge : clean
|
|||
|
||||
help :
|
||||
@make -f Makefile_atheros help
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -114,3 +114,8 @@ $(TARGET).semistatic (version sans lien dynamique vers libowlps)."
|
|||
@echo
|
||||
@echo "Note : l'installation se fait dans l'arborescence $(PREFIX). \
|
||||
Modifiez la variable PREFIX du Makefile pour changer ce comportement."
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -157,7 +157,7 @@ void parse_main_options(int argc, char **argv)
|
|||
// Take the optind value:
|
||||
options.flood_delay =
|
||||
strtoul(argv[optind], NULL, 0) ;
|
||||
optind++ ;
|
||||
++optind ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
@ -185,7 +185,7 @@ void parse_main_options(int argc, char **argv)
|
|||
// Take the optind value:
|
||||
options.listening_port =
|
||||
strtoul(argv[optind], NULL, 0) ;
|
||||
optind++ ;
|
||||
++optind ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
|
|
|
@ -101,3 +101,8 @@ purge : clean
|
|||
|
||||
help :
|
||||
@make help
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -97,3 +97,8 @@ purge : clean
|
|||
|
||||
help :
|
||||
@make help
|
||||
|
||||
|
||||
# Local Variables: *
|
||||
# mode: makefile-gmake *
|
||||
# End: *
|
||||
|
|
|
@ -71,11 +71,89 @@ enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ;
|
|||
#define VERBOSE_CHATTERBOX GET_VERBOSE() >= 3
|
||||
|
||||
|
||||
/* Packet header sizes (in bytes) */
|
||||
#define IEEE80211_HEADER_SIZE_DATA 24 // Header size for a Data frame
|
||||
#define LLC_HEADER_SIZE 8
|
||||
|
||||
/* IEEE 802.11 frame types */
|
||||
// Beacon (TODO: convert to mask)
|
||||
#define RAW_PACKET_TYPE_BEACON 0x80
|
||||
|
||||
// Data frame
|
||||
#define FRAME_TYPE_DATA_MASK 0x08
|
||||
#define IS_DATA_FRAME(FC1) \
|
||||
(((FC1) & FRAME_TYPE_DATA_MASK) == FRAME_TYPE_DATA_MASK)
|
||||
|
||||
// QoS Data frame
|
||||
#define FRAME_SUBTYPE_QOS_MASK 0x80
|
||||
#define DATA_FRAME_IS_QOS(FC1) \
|
||||
(((FC1) & FRAME_SUBTYPE_QOS_MASK) == FRAME_SUBTYPE_QOS_MASK)
|
||||
|
||||
// To/From DS
|
||||
#define FRAME_FROM_STA_MASK 0x02
|
||||
#define IS_FRAME_FROM_STA(FC2) \
|
||||
(((FC2) & FRAME_FROM_STA_MASK) != FRAME_FROM_STA_MASK)
|
||||
|
||||
|
||||
/* Positions of the radiotap header fixed fields (in bytes) */
|
||||
#define RTAP_P_HREVISION 0 // Header revision
|
||||
#define RTAP_P_HPAD 1 // Header pad
|
||||
#define RTAP_P_HLENGTH 2 // Header length
|
||||
#define RTAP_P_PRESENTFLAGS 4 // Present flags
|
||||
|
||||
|
||||
/* Radiotap field lengths (in bytes) */
|
||||
#define RTAP_L_HREVISION 1 // Header revision
|
||||
#define RTAP_L_HPAD 1 // Header pad
|
||||
#define RTAP_L_HLENGTH 2 // Header length
|
||||
#define RTAP_L_PRESENTFLAGS 4 // Present flags
|
||||
#define RTAP_L_MACTS 8 // MAC timestamp (Time Synchronization Function Timer)
|
||||
#define RTAP_L_FLAGS 1 // autre champ de flags
|
||||
#define RTAP_L_RATE 1 // Data rate
|
||||
#define RTAP_L_CHANNEL 2 // Channel frequency
|
||||
#define RTAP_L_CHANNELTYPE 2 // Channel type
|
||||
#define RTAP_L_ANTENNASIGNALDBM 1 // SSI signal (dBm)
|
||||
#define RTAP_L_ANTENNANOISEDBM 1 // SSI noise (dBm)
|
||||
#define RTAP_L_ANTENNA 1 // Antenna number
|
||||
#define RTAP_L_FHSS 2 // Hop set and pattern for Frequency-Hopping Spread Spectrum
|
||||
#define RTAP_L_LOCKQUALITY 2 // Signal quality
|
||||
#define RTAP_L_TXATTENUATION 2 // Transmit power from max power
|
||||
#define RTAP_L_TXATTENUATIONDB 2 // Idem (dB)
|
||||
#define RTAP_L_TXATTENUATIONDBM 1 // Idem (dBm)
|
||||
#define RTAP_L_ANTENNASIGNALDB 1 // SSI signal (dB)
|
||||
#define RTAP_L_ANTENNANOISEDB 1 // SSI noise (dB)
|
||||
#define RTAP_L_FCS 4 // Frame Check Sequence
|
||||
//#define RTAP_L_CHANNELP // Extended channel info (not implemented)
|
||||
//#define RTAP_L_EXT // Present flags' extension (not emplemented)
|
||||
|
||||
|
||||
/* Positions in 'Present flags' (and present fields 'check' array) */
|
||||
#define RTAP_MACTS 0
|
||||
#define RTAP_FLAGS 1
|
||||
#define RTAP_RATE 2
|
||||
#define RTAP_CHANNEL 3 // and RTAP_CHANNELTYPE
|
||||
#define RTAP_FHSS 4
|
||||
#define RTAP_ANTENNASIGNALDBM 5
|
||||
#define RTAP_ANTENNANOISEDBM 6
|
||||
#define RTAP_LOCKQUALITY 7
|
||||
#define RTAP_TXATTENUATION 8
|
||||
#define RTAP_TXATTENUATIONDB 9
|
||||
#define RTAP_TXATTENUATIONDBM 10
|
||||
#define RTAP_ANTENNA 11
|
||||
#define RTAP_ANTENNASIGNALDB 12
|
||||
#define RTAP_ANTENNANOISEDB 13
|
||||
#define RTAP_FCS 14
|
||||
//#define RTAP_CHANNELP 18
|
||||
//#define RTAP_EXT 31
|
||||
|
||||
|
||||
/* Error codes */
|
||||
#define ERR_OPENING_IFACE 2 // Error when opening capture interface
|
||||
#define ERR_BAD_USAGE 3 // Bad program call
|
||||
#define ERR_PARSING_CONFIG_FILE 4 // Error reading the configuration file
|
||||
#define ERR_CREATING_THREAD 6 // Error creating a thread
|
||||
#define ERR_SETTING_MODE 101
|
||||
#define ERR_READING_MODE 104
|
||||
|
||||
|
||||
/* Function headers */
|
||||
|
@ -98,6 +176,11 @@ int iface_mode_monitor(const char *const iface) ;
|
|||
int capture(void) ;
|
||||
void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
||||
const u_char *packet) ;
|
||||
void extract_calibration_data(const u_char *packet,
|
||||
owl_captured_request *request) ;
|
||||
void extract_radiotap_data(const u_char *packet,
|
||||
owl_captured_request *request,
|
||||
owl_bool rtap_fields[15]) ;
|
||||
void get_mac_addr(char *eth, uint8_t mac_bytes[ETHER_ADDR_LEN]) ;
|
||||
void get_ip_addr(char *eth, char *ip_bytes) ;
|
||||
|
||||
|
|
|
@ -770,12 +770,9 @@ int capture()
|
|||
void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
||||
const u_char *packet)
|
||||
{
|
||||
uint16_t rtap_bytes ; // Received data size
|
||||
uint32_t rtap_presentflags ;
|
||||
uint_fast16_t rtap_position ;
|
||||
owl_captured_request request ; // Message to send to the aggregator
|
||||
ssize_t nsent ; // sendto return value
|
||||
owl_bool check[15] ; // Present flags
|
||||
uint16_t rtap_bytes ; // Radiotap header size
|
||||
owl_bool rtap_fields[15] ; // Present flags
|
||||
uint8_t raw_packet_fc1 ; // First byte of the received frame's FC
|
||||
uint8_t raw_packet_fc2 ; // Second byte of the received frame's FC
|
||||
uint8_t raw_packet_flags ; // IEEE 802.11 header flags
|
||||
|
@ -790,7 +787,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
|||
owl_bool is_explicit_packet = TRUE ; // Is the packet an explicit request?
|
||||
// Is the packet an autocalibration positioning request?
|
||||
owl_bool uses_autocalibration_request_port = FALSE ;
|
||||
int i ; // Iterator
|
||||
ssize_t nsent ; // sendto return value
|
||||
|
||||
// Blank the request:
|
||||
memset(&request, 0, sizeof(request)) ;
|
||||
|
@ -909,21 +906,12 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
|||
case OWL_REQUEST_CALIBRATION :
|
||||
if (VERBOSE_INFO)
|
||||
printf("\nExplicit calibration packet received.\n") ;
|
||||
request.direction =
|
||||
packet[rtap_bytes + ieee80211_header_size + LLC_HEADER_SIZE
|
||||
+ sizeof(struct iphdr) + sizeof(struct udphdr) + 9];
|
||||
memcpy(&request.x_position,
|
||||
&packet[rtap_bytes + ieee80211_header_size
|
||||
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
|
||||
+ sizeof(struct udphdr) + 10], sizeof(float)) ;
|
||||
memcpy(&request.y_position,
|
||||
&packet[rtap_bytes + ieee80211_header_size
|
||||
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
|
||||
+ sizeof(struct udphdr) + 14], sizeof(float)) ;
|
||||
memcpy(&request.z_position,
|
||||
&packet[rtap_bytes + ieee80211_header_size
|
||||
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
|
||||
+ sizeof(struct udphdr) + 18], sizeof(float)) ;
|
||||
extract_calibration_data(&packet[rtap_bytes +
|
||||
ieee80211_header_size +
|
||||
LLC_HEADER_SIZE
|
||||
+ sizeof(struct iphdr) +
|
||||
sizeof(struct udphdr) + 9],
|
||||
&request) ;
|
||||
break ;
|
||||
|
||||
case OWL_REQUEST_AUTOCALIBRATION :
|
||||
|
@ -934,21 +922,12 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
|||
printf(".. on the wrong port!") ;
|
||||
putchar('\n') ;
|
||||
}
|
||||
request.direction =
|
||||
packet[rtap_bytes + ieee80211_header_size + LLC_HEADER_SIZE
|
||||
+ sizeof(struct iphdr) + sizeof(struct udphdr) + 9];
|
||||
memcpy(&request.x_position,
|
||||
&packet[rtap_bytes + ieee80211_header_size
|
||||
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
|
||||
+ sizeof(struct udphdr) + 10], sizeof(float)) ;
|
||||
memcpy(&request.y_position,
|
||||
&packet[rtap_bytes + ieee80211_header_size
|
||||
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
|
||||
+ sizeof(struct udphdr) + 14], sizeof(float)) ;
|
||||
memcpy(&request.z_position,
|
||||
&packet[rtap_bytes + ieee80211_header_size
|
||||
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
|
||||
+ sizeof(struct udphdr) + 18], sizeof(float)) ;
|
||||
extract_calibration_data(&packet[rtap_bytes +
|
||||
ieee80211_header_size +
|
||||
LLC_HEADER_SIZE
|
||||
+ sizeof(struct iphdr) +
|
||||
sizeof(struct udphdr) + 9],
|
||||
&request) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
|
@ -991,96 +970,8 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
|||
else // Active mode, packet was not an explicit request
|
||||
return ;
|
||||
|
||||
|
||||
/* Radiotap header handling */
|
||||
|
||||
// Get rtap flags:
|
||||
memcpy(&rtap_presentflags,
|
||||
&packet[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS) ;
|
||||
// Radiotap header is little-endian
|
||||
rtap_presentflags = le32toh(rtap_presentflags) ;
|
||||
|
||||
for (i = 0 ; i < 15 ; i++) // Initialise present flags structure
|
||||
check[i] = FALSE ;
|
||||
rtap_position = 8 ; // Begining of the present flags determined fields
|
||||
|
||||
// Test the first 15 bits of the flag field in order to check their
|
||||
// presence and to copy them:
|
||||
for (i = 0 ; i < 15 ; i++)
|
||||
{
|
||||
if ((rtap_presentflags % 2) == 1)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case RTAP_MACTS:
|
||||
check[RTAP_MACTS] = TRUE ;
|
||||
rtap_position += RTAP_L_MACTS ;
|
||||
break ;
|
||||
case RTAP_FLAGS:
|
||||
check[RTAP_FLAGS] = TRUE;
|
||||
rtap_position += RTAP_L_FLAGS ;
|
||||
break ;
|
||||
case RTAP_RATE:
|
||||
check[RTAP_RATE] = TRUE;
|
||||
rtap_position += RTAP_L_RATE ;
|
||||
break ;
|
||||
case RTAP_CHANNEL:
|
||||
rtap_position += RTAP_L_CHANNEL ;
|
||||
rtap_position += RTAP_L_CHANNELTYPE ;
|
||||
break ;
|
||||
case RTAP_FHSS:
|
||||
check[RTAP_FHSS] = TRUE;
|
||||
rtap_position += RTAP_L_FHSS ;
|
||||
break ;
|
||||
case RTAP_ANTENNASIGNALDBM:
|
||||
memcpy(&(request.antenna_signal_dbm),
|
||||
&packet[rtap_position], RTAP_L_ANTENNASIGNALDBM) ;
|
||||
check[RTAP_ANTENNASIGNALDBM] = TRUE;
|
||||
if (VERBOSE_INFO)
|
||||
printf("Antenna signal: %d dBm\n",
|
||||
request.antenna_signal_dbm - 0x100);
|
||||
rtap_position += RTAP_L_ANTENNASIGNALDBM ;
|
||||
break ;
|
||||
case RTAP_ANTENNANOISEDBM:
|
||||
check[RTAP_ANTENNANOISEDBM] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNANOISEDBM ;
|
||||
break ;
|
||||
case RTAP_LOCKQUALITY:
|
||||
check[RTAP_LOCKQUALITY] = TRUE;
|
||||
rtap_position += RTAP_L_LOCKQUALITY ;
|
||||
break ;
|
||||
case RTAP_TXATTENUATION:
|
||||
check[RTAP_TXATTENUATION] = TRUE;
|
||||
rtap_position += RTAP_L_TXATTENUATION ;
|
||||
break ;
|
||||
case RTAP_TXATTENUATIONDB:
|
||||
check[RTAP_TXATTENUATIONDB] = TRUE;
|
||||
rtap_position += RTAP_L_TXATTENUATIONDB ;
|
||||
break ;
|
||||
case RTAP_TXATTENUATIONDBM:
|
||||
check[RTAP_TXATTENUATIONDBM] = TRUE;
|
||||
rtap_position += RTAP_L_TXATTENUATIONDBM ;
|
||||
break ;
|
||||
case RTAP_ANTENNA:
|
||||
check[RTAP_ANTENNA] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNA ;
|
||||
break ;
|
||||
case RTAP_ANTENNASIGNALDB:
|
||||
check[RTAP_ANTENNASIGNALDB] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNASIGNALDB ;
|
||||
break ;
|
||||
case RTAP_ANTENNANOISEDB:
|
||||
check[RTAP_ANTENNANOISEDB] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNANOISEDB ;
|
||||
break ;
|
||||
case RTAP_FCS:
|
||||
check[RTAP_FCS] = TRUE;
|
||||
rtap_position += RTAP_L_FCS ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
rtap_presentflags /= 2 ;
|
||||
}
|
||||
extract_radiotap_data(packet, &request, rtap_fields) ;
|
||||
|
||||
/* Display the packet details */
|
||||
if (GET_DISPLAY_CAPTURED())
|
||||
|
@ -1109,7 +1000,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
|||
owl_mac_bytes_to_string(request.mobile_mac_addr_bytes),
|
||||
request_time_str,
|
||||
start_time_str,
|
||||
check[RTAP_ANTENNASIGNALDBM] ?
|
||||
rtap_fields[RTAP_ANTENNASIGNALDBM] ?
|
||||
request.antenna_signal_dbm - 0x100 : 0,
|
||||
owl_ntohf(request.x_position),
|
||||
owl_ntohf(request.y_position),
|
||||
|
@ -1132,6 +1023,126 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
|
|||
|
||||
|
||||
|
||||
/*
|
||||
* Fills 'request' with the calibration data extracted from 'packet'.
|
||||
* Note: 'packet' is read from its first byte, therefore you must not
|
||||
* pass the whole received packet to this function.
|
||||
*/
|
||||
void extract_calibration_data(const u_char *packet,
|
||||
owl_captured_request *request)
|
||||
{
|
||||
request->direction = packet[0] ;
|
||||
memcpy(&request->x_position, &packet[1], sizeof(float)) ;
|
||||
memcpy(&request->y_position, &packet[4], sizeof(float)) ;
|
||||
memcpy(&request->z_position, &packet[8], sizeof(float)) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Fills 'request' with the required data extracted from the Radiotap
|
||||
* header of 'packet'. The elements of 'rtap_fields' are set to TRUE
|
||||
* when the corresponding Radiotap flag is found in the packet.
|
||||
*/
|
||||
void extract_radiotap_data(const u_char *packet,
|
||||
owl_captured_request *request,
|
||||
owl_bool rtap_fields[15])
|
||||
{
|
||||
uint32_t rtap_presentflags ;
|
||||
uint_fast16_t rtap_position ;
|
||||
int i ; // Iterator
|
||||
|
||||
// Get rtap flags:
|
||||
memcpy(&rtap_presentflags,
|
||||
&packet[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS) ;
|
||||
// The Radiotap header is little-endian
|
||||
rtap_presentflags = le32toh(rtap_presentflags) ;
|
||||
|
||||
for (i = 0 ; i < 15 ; ++i) // Initialise present flags structure
|
||||
rtap_fields[i] = FALSE ;
|
||||
rtap_position = 8 ; // Begining of the present flags determined fields
|
||||
|
||||
// Test the first 15 bits of the flag field in order to check their
|
||||
// presence and to copy them:
|
||||
for (i = 0 ; i < 15 ; ++i)
|
||||
{
|
||||
if ((rtap_presentflags % 2) == 1)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case RTAP_MACTS:
|
||||
rtap_fields[RTAP_MACTS] = TRUE ;
|
||||
rtap_position += RTAP_L_MACTS ;
|
||||
break ;
|
||||
case RTAP_FLAGS:
|
||||
rtap_fields[RTAP_FLAGS] = TRUE;
|
||||
rtap_position += RTAP_L_FLAGS ;
|
||||
break ;
|
||||
case RTAP_RATE:
|
||||
rtap_fields[RTAP_RATE] = TRUE;
|
||||
rtap_position += RTAP_L_RATE ;
|
||||
break ;
|
||||
case RTAP_CHANNEL:
|
||||
rtap_position += RTAP_L_CHANNEL ;
|
||||
rtap_position += RTAP_L_CHANNELTYPE ;
|
||||
break ;
|
||||
case RTAP_FHSS:
|
||||
rtap_fields[RTAP_FHSS] = TRUE;
|
||||
rtap_position += RTAP_L_FHSS ;
|
||||
break ;
|
||||
case RTAP_ANTENNASIGNALDBM:
|
||||
memcpy(&request->antenna_signal_dbm,
|
||||
&packet[rtap_position], RTAP_L_ANTENNASIGNALDBM) ;
|
||||
rtap_fields[RTAP_ANTENNASIGNALDBM] = TRUE;
|
||||
if (VERBOSE_INFO)
|
||||
printf("Antenna signal: %d dBm\n",
|
||||
request->antenna_signal_dbm - 0x100);
|
||||
rtap_position += RTAP_L_ANTENNASIGNALDBM ;
|
||||
break ;
|
||||
case RTAP_ANTENNANOISEDBM:
|
||||
rtap_fields[RTAP_ANTENNANOISEDBM] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNANOISEDBM ;
|
||||
break ;
|
||||
case RTAP_LOCKQUALITY:
|
||||
rtap_fields[RTAP_LOCKQUALITY] = TRUE;
|
||||
rtap_position += RTAP_L_LOCKQUALITY ;
|
||||
break ;
|
||||
case RTAP_TXATTENUATION:
|
||||
rtap_fields[RTAP_TXATTENUATION] = TRUE;
|
||||
rtap_position += RTAP_L_TXATTENUATION ;
|
||||
break ;
|
||||
case RTAP_TXATTENUATIONDB:
|
||||
rtap_fields[RTAP_TXATTENUATIONDB] = TRUE;
|
||||
rtap_position += RTAP_L_TXATTENUATIONDB ;
|
||||
break ;
|
||||
case RTAP_TXATTENUATIONDBM:
|
||||
rtap_fields[RTAP_TXATTENUATIONDBM] = TRUE;
|
||||
rtap_position += RTAP_L_TXATTENUATIONDBM ;
|
||||
break ;
|
||||
case RTAP_ANTENNA:
|
||||
rtap_fields[RTAP_ANTENNA] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNA ;
|
||||
break ;
|
||||
case RTAP_ANTENNASIGNALDB:
|
||||
rtap_fields[RTAP_ANTENNASIGNALDB] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNASIGNALDB ;
|
||||
break ;
|
||||
case RTAP_ANTENNANOISEDB:
|
||||
rtap_fields[RTAP_ANTENNANOISEDB] = TRUE;
|
||||
rtap_position += RTAP_L_ANTENNANOISEDB ;
|
||||
break ;
|
||||
case RTAP_FCS:
|
||||
rtap_fields[RTAP_FCS] = TRUE;
|
||||
rtap_position += RTAP_L_FCS ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
rtap_presentflags /= 2 ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Get our own MAC address and copy it to 'mac_bytes'.
|
||||
*/
|
||||
|
|
|
@ -101,6 +101,7 @@ OBJ_NOTEST_LIST = \
|
|||
posexcept.o \
|
||||
multilaterationalgorithm.o \
|
||||
cartographyalgorithm.o \
|
||||
outputnetworksocket.o \
|
||||
inputmedium.o
|
||||
INTERFACES_LIST = \
|
||||
inputlogmedium.hh \
|
||||
|
@ -214,17 +215,24 @@ $(OBJ_DIR)/csvfilereader.o: \
|
|||
$(OBJ_DIR)/textfilereader.o
|
||||
$(OBJ_DIR)/textfilewriter.o: \
|
||||
$(OBJ_DIR)/posexcept.o
|
||||
$(OBJ_DIR)/inputmedium.o: \
|
||||
$(OBJ_DIR)/calibrationrequest.o \
|
||||
$(OBJ_DIR)/posexcept.o \
|
||||
$(OBJ_DIR)/configuration.o \
|
||||
$(OBJ_DIR)/stock.o
|
||||
$(OBJ_DIR)/inputcsv.o: \
|
||||
$(OBJ_DIR)/inputmedium.o \
|
||||
$(OBJ_DIR)/csvfilereader.o \
|
||||
$(OBJ_DIR)/request.o \
|
||||
$(OBJ_DIR)/calibrationrequest.o \
|
||||
$(OBJ_DIR)/configuration.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)/configuration.o \
|
||||
$(OBJ_DIR)/stock.o
|
||||
$(OBJ_DIR)/inputlogcsv.o: \
|
||||
$(SRC_DIR)/inputlogmedium.hh \
|
||||
|
@ -246,12 +254,24 @@ $(OBJ_DIR)/outputcsv.o: \
|
|||
$(OBJ_DIR)/textfilewriter.o \
|
||||
$(OBJ_DIR)/resultlist.o \
|
||||
$(OBJ_DIR)/result.o
|
||||
$(OBJ_DIR)/outputnetworksocket.o: \
|
||||
$(SRC_DIR)/outputmedium.hh \
|
||||
$(OBJ_DIR)/resultlist.o \
|
||||
$(OBJ_DIR)/result.o
|
||||
$(OBJ_DIR)/outputudpsocket.o: \
|
||||
$(SRC_DIR)/outputmedium.hh \
|
||||
$(OBJ_DIR)/result.o
|
||||
$(OBJ_DIR)/outputnetworksocket.o \
|
||||
$(OBJ_DIR)/request.o \
|
||||
$(OBJ_DIR)/resultlist.o \
|
||||
$(OBJ_DIR)/result.o \
|
||||
$(OBJ_DIR)/posexcept.o
|
||||
$(OBJ_DIR)/outputtcpsocketevaal.o: \
|
||||
$(SRC_DIR)/outputmedium.hh \
|
||||
$(OBJ_DIR)/result.o
|
||||
$(OBJ_DIR)/outputnetworksocket.o \
|
||||
$(OBJ_DIR)/request.o \
|
||||
$(OBJ_DIR)/resultlist.o \
|
||||
$(OBJ_DIR)/result.o \
|
||||
$(OBJ_DIR)/area.o \
|
||||
$(OBJ_DIR)/posexcept.o \
|
||||
$(OBJ_DIR)/stock.o
|
||||
$(OBJ_DIR)/outputcsv.o: \
|
||||
$(SRC_DIR)/outputmedium.hh \
|
||||
$(OBJ_DIR)/result.o
|
||||
|
@ -278,7 +298,9 @@ $(OBJ_DIR)/minmax.o: \
|
|||
$(OBJ_DIR)/interlinknetworks.o: \
|
||||
$(OBJ_DIR)/multilaterationalgorithm.o
|
||||
$(OBJ_DIR)/fbcm.o: \
|
||||
$(OBJ_DIR)/multilaterationalgorithm.o
|
||||
$(OBJ_DIR)/multilaterationalgorithm.o \
|
||||
$(OBJ_DIR)/configuration.o \
|
||||
$(OBJ_DIR)/stock.o
|
||||
$(OBJ_DIR)/frbhmbasic.o: \
|
||||
$(OBJ_DIR)/radar.o \
|
||||
$(OBJ_DIR)/fbcm.o
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
|
||||
- Known bugs
|
||||
° FBCM always gives the same result.
|
||||
° Cannot compute the error (Real) with autocalibration requests.
|
||||
|
||||
- Algorithms
|
||||
° Check MultilaterationAlgorithm::make_constant_term().
|
||||
Hint: mobile.trx_power() vs. ap.trx_power().
|
||||
° MinMax: use a different step for X, Y and Z?
|
||||
|
||||
- Autocalibration
|
||||
° Generate reference points in 3D.
|
||||
° Handle 2 APs, not only >2 APs.
|
||||
° Find why some CalibrationRequest were not deleted when
|
||||
calling Stock::delete_calibration_request() (via
|
||||
ReferencePoint::delete_requests()).
|
||||
|
||||
- Refactoring
|
||||
° Split Stock::regenerate_reference_points() into several
|
||||
functions.
|
||||
° Create virtual class OutputSocket to factorise code of
|
||||
OutputUDPSocket & OutputTCPSocketEvAAL.
|
||||
° Synchronise InputCSV & InputUDPSocket (calibration requests),
|
||||
factorise code into InputMedium.
|
||||
° Write a class for Request::type?
|
||||
CalibrationRequest::direction uses a dedicated class Direction, why
|
||||
not Request::type? That would simplify writing of the type to
|
||||
streams (no need to cast each time anymore).
|
||||
° Wi-Fi devices' list
|
||||
. Merge Stock::mobiles & Stock::aps?
|
||||
. Factorise AccessPointsReaderCSV & MobilesReaderCSV?
|
||||
° Members renaming
|
||||
. InputMedium:
|
||||
. - current_line_nb & get_current_line_nb()
|
||||
. - get_next_request() −> read_next_request()
|
||||
. Input: get_next_request() −> read_next_request()
|
||||
. Area: p_min et p_max −> coord_min et coord_max
|
||||
|
||||
- User interface
|
||||
° Add the area to the result in OutputCSV.
|
||||
° When reading the APs, add them to the mobiles' list (or another
|
||||
way to be able to have a single entry for an AP).
|
||||
° Rename minmax-start & stop, since it is used elsewhere (grep
|
||||
minmax-start).
|
||||
° Review the option names & descriptions.
|
||||
° Add option positioning.self-calibrate (or autocalibrate), to
|
||||
activate automatically the options needed by the autocalibration.
|
||||
° Improve --verbose (and/or debug level): print the options, etc.
|
||||
° Case-insensitive string comparison (for algorithm names, etc.).
|
||||
° Use a prefix for configuration files (search for config files set
|
||||
with relative path in owlps-positioning.cfg in the same directory).
|
||||
|
||||
- Optimisation & code improvement
|
||||
° Multithread algorithm calls.
|
||||
° ReferencePoint: the request list should be an unordered_set
|
||||
instead of a vector, to guarantee the unicity of the elements.
|
||||
|
||||
- Unit tests
|
||||
° Update tests (currently unmaintained).
|
||||
° Unfinished tests:
|
||||
. InputDataReader
|
||||
. Input
|
||||
. Output
|
||||
. Positioning
|
||||
° Test InterlinkNetworks::compute() ?
|
||||
° Timestamp: there is a probability of 10^-6 that the value in
|
||||
nanoseconds and the rounded value in milliseconds are identical, in
|
||||
which case some tests can fail.
|
||||
|
||||
- Revoir le diagramme UML
|
||||
° Associations : devraient êtres représentées par des attributs
|
||||
pointeurs.
|
||||
° Compositions : devraient être représentées par des attributs
|
||||
normaux.
|
||||
|
||||
- « C++ en action »
|
||||
° Espaces de noms ? 109
|
||||
° Réserver l'espace mémoire des vector avec reserve(). 217
|
||||
° Copie de conteneur vers un flux (cas de certains operator<<). 275
|
||||
|
||||
- « Coder proprement »
|
||||
° Revoir toutes les classes pour respecter si possible les
|
||||
principes exposés dans le chapitre 6 (p. 103) : implanter
|
||||
systématiquement des accesseurs pour tous les attributs d'une
|
||||
classe expose l'implantation de la classe et rend ses attributs
|
||||
publics. La classe Direction (et maintenant Timestamp) tend à
|
||||
respecter ce principe en utilisant mieux les opérateurs et en ne
|
||||
proposant pas d'accesseur direct.
|
|
@ -49,13 +49,16 @@ csv-file = /tmp/owlps-positioning.log
|
|||
#algorithm = RADAR
|
||||
#algorithm = FRBHMBasic
|
||||
|
||||
# Start and stop coordinates for the MinMax multilateration method.
|
||||
# Coordinates of the deployment area.
|
||||
# This is used to delimit the area in which reference points are
|
||||
# generated (when generate-reference-points is activated), and also
|
||||
# by the MinMax multilateration method.
|
||||
# Since MinMax is currently the only multilateration method implemented
|
||||
# in OwlPS, you should define these parameters if you use any of the
|
||||
# multilateration-based algorithms (InterlinkNetworks, FBCM, FRBHM).
|
||||
# They are declared as strings (X;Y;Z). Do not quote!
|
||||
#minmax-start = -2;-2;0
|
||||
#minmax-stop = 20;30;6
|
||||
#area-start = -2;-2;0
|
||||
#area-stop = 20;30;6
|
||||
|
||||
# With the RADAR algorithm, for a given positioning request, average
|
||||
# all the calibration requests associated with a reference point before
|
||||
|
@ -123,3 +126,16 @@ csv-file = /tmp/owlps-positioning.log
|
|||
|
||||
#medium = CSV
|
||||
csv-file = /tmp/owlps-positioning.out
|
||||
|
||||
#medium = UDP
|
||||
# Currently, the host must be an IP address (not a DNS name).
|
||||
#udp-host =
|
||||
#udp-port = 9910
|
||||
|
||||
# Note: you can use only one algorithm when using the TCPEvAAL output.
|
||||
#medium = TCPEvAAL
|
||||
# Currently, the host must be an IP address (not a DNS name).
|
||||
#tcpevaal-host = 127.0.0.1
|
||||
#tcpevaal-port = 4444
|
||||
|
||||
# vim: syntax=cfg
|
|
@ -5,12 +5,17 @@
|
|||
# handle it. Since none of them are currently implemented, you
|
||||
# probably can save a lot of time by skipping the topology (and
|
||||
# waypoints) description.
|
||||
# However, you can describe areas if you want to know when the mobile
|
||||
# is in a particular location. In that case be sure that the algorithm
|
||||
# you use will be able to generate positions that match each described
|
||||
# area (in particular, with RADAR, at least one reference point should
|
||||
# be present in each area).
|
||||
#
|
||||
# ALSO IMPORTANT (EVEN IF YOU DON'T DESCRIBE THE TOPOLOGY):
|
||||
# If you use the MinMax multilateration method, you should provide
|
||||
# minmax-start and minmax-stop parameters that match the deployment
|
||||
# area. That is, the cuboid formed by these two points should include
|
||||
# the whole deployment area.
|
||||
# If you use the MinMax multilateration method, or the autocalibration,
|
||||
# you must provide area-start and area-stop options that match the
|
||||
# deployment area. That is, the cuboid formed by these two points
|
||||
# should include the whole deployment area.
|
||||
#
|
||||
# This file lists the buildings and their "homogeneous areas" (rooms).
|
||||
#
|
||||
|
|
Can't render this file because it contains an unexpected character in line 20 and column 43.
|
|
@ -5,10 +5,22 @@ using namespace std ;
|
|||
|
||||
|
||||
|
||||
/* *** Operations *** */
|
||||
|
||||
|
||||
double AccessPoint::friis_constant_term() const
|
||||
{
|
||||
double wavelength =
|
||||
static_cast<double>(PosUtil::LIGHT_SPEED) / frequency ;
|
||||
return antenna_gain + 20 * log10(wavelength) - 20 * log10(4 * M_PI) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Operators *** */
|
||||
|
||||
|
||||
const AccessPoint& AccessPoint::operator=(const AccessPoint &source)
|
||||
AccessPoint& AccessPoint::operator=(const AccessPoint &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
|
|
@ -67,9 +67,15 @@ public:
|
|||
void set_friis_index(const float _friis_index) ;
|
||||
//@}
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
/// Returns the Friis formula's constant term
|
||||
double friis_constant_term(void) const ;
|
||||
//@}
|
||||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const AccessPoint& operator=(const AccessPoint &source) ;
|
||||
AccessPoint& operator=(const AccessPoint &source) ;
|
||||
bool operator==(const AccessPoint &source) const ;
|
||||
bool operator!=(const AccessPoint &source) const ;
|
||||
//@}
|
||||
|
|
|
@ -119,7 +119,7 @@ void Area::reorder_coordinates()
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Area& Area::operator=(const Area &source)
|
||||
Area& Area::operator=(const Area &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Area& operator=(const Area &source) ;
|
||||
Area& operator=(const Area &source) ;
|
||||
bool operator==(const Area &source) const ;
|
||||
bool operator!=(const Area &source) const ;
|
||||
//@}
|
||||
|
|
|
@ -73,7 +73,7 @@ void Building::add_area(Area *&area)
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Building& Building::operator=(const Building &source)
|
||||
Building& Building::operator=(const Building &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
|
|
@ -48,7 +48,7 @@ public :
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Building& operator=(const Building &source) ;
|
||||
Building& operator=(const Building &source) ;
|
||||
bool operator==(const Building &source) const ;
|
||||
bool operator!=(const Building &source) const ;
|
||||
//@}
|
||||
|
|
|
@ -54,8 +54,8 @@ void CalibrationRequest::clear()
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const CalibrationRequest&
|
||||
CalibrationRequest::operator=(const CalibrationRequest &source)
|
||||
CalibrationRequest& CalibrationRequest::
|
||||
operator=(const CalibrationRequest &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
@ -68,7 +68,8 @@ CalibrationRequest::operator=(const CalibrationRequest &source)
|
|||
}
|
||||
|
||||
|
||||
bool CalibrationRequest::operator==(const CalibrationRequest &source) const
|
||||
bool CalibrationRequest::
|
||||
operator==(const CalibrationRequest &source) const
|
||||
{
|
||||
if (this == &source)
|
||||
return true ;
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const CalibrationRequest& operator=(const CalibrationRequest &source) ;
|
||||
CalibrationRequest& operator=(const CalibrationRequest &source) ;
|
||||
bool operator==(const CalibrationRequest &source) const ;
|
||||
bool operator!=(const CalibrationRequest &source) const ;
|
||||
//@}
|
||||
|
|
|
@ -36,14 +36,14 @@ inline bool Direction::is_valid() const
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Direction& Direction::operator=(const Direction &source)
|
||||
Direction& Direction::operator=(const Direction &source)
|
||||
{
|
||||
direction = source.direction ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
|
||||
const Direction& Direction::operator=(const char source)
|
||||
Direction& Direction::operator=(const char source)
|
||||
{
|
||||
direction = source ;
|
||||
assert_valid() ;
|
||||
|
|
|
@ -27,8 +27,8 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Direction& operator=(const Direction &source) ;
|
||||
const Direction& operator=(const char source) ;
|
||||
Direction& operator=(const Direction &source) ;
|
||||
Direction& operator=(const char source) ;
|
||||
bool operator==(const Direction &source) const ;
|
||||
bool operator!=(const Direction &source) const ;
|
||||
operator bool(void) const ;
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
#include "fbcm.hh"
|
||||
#include "stock.hh"
|
||||
#include "configuration.hh"
|
||||
|
||||
|
||||
|
||||
Result FBCM::compute(const Request &_request)
|
||||
{
|
||||
// If the autocalibration is activated, we have to regenerate the
|
||||
// Friis indexes each time we calculate a position
|
||||
if (Configuration::bool_value("positioning.generate-reference-points"))
|
||||
Stock::update_all_friis_indexes() ;
|
||||
return MultilaterationAlgorithm::compute(_request) ;
|
||||
}
|
||||
|
||||
|
||||
float FBCM::estimate_distance(const Measurement &measurement)
|
||||
{
|
||||
double constant_term = make_constant_term(measurement) ;
|
||||
|
|
|
@ -13,7 +13,11 @@ public:
|
|||
FBCM(void): PositioningAlgorithm("FBCM") {}
|
||||
~FBCM(void) {}
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
Result compute(const Request &_request) ;
|
||||
float estimate_distance(const Measurement &measurement) ;
|
||||
//@}
|
||||
} ;
|
||||
|
||||
#endif // _OWLPS_POSITIONING_FBCM_HH_
|
||||
|
|
|
@ -17,24 +17,18 @@ using std::tr1::unordered_map ;
|
|||
|
||||
|
||||
/**
|
||||
* This function reads the next Request in the CSV input file. Blank
|
||||
* lines and lines containing only spaces are skipped.
|
||||
* This function fills the current Request from the CSV input file.
|
||||
* Blank lines and lines containing only spaces are skipped until a line
|
||||
* containing a request is found.
|
||||
*
|
||||
* #file should be opened before proceeding requests; otherwise,
|
||||
* #current_request is \link Request::clear() cleared\endlink and a
|
||||
* blank Request is returned. The file must be valid,
|
||||
* semicolon-separated (\em not comma-separated).
|
||||
*
|
||||
* @return The read Request, or a blank Request in case of error (file
|
||||
* not opened, end of file, invalid field or wrong number of fields in
|
||||
* the line).
|
||||
* @returns \em true if #current_request was correctly filled.
|
||||
* @returns \em false in case of error (file not opened, end of file,
|
||||
* invalid field or wrong number of fields in the line).
|
||||
*/
|
||||
const Request& InputCSV::get_next_request()
|
||||
bool InputCSV::fill_current_request()
|
||||
{
|
||||
clear_current_request() ;
|
||||
|
||||
if (! file.next_line()) // End of file or error
|
||||
return *current_request ;
|
||||
return false ;
|
||||
++current_line_nb ;
|
||||
|
||||
// Read Mobile MAC field
|
||||
|
@ -43,13 +37,13 @@ const Request& InputCSV::get_next_request()
|
|||
{
|
||||
if (Configuration::is_configured("verbose"))
|
||||
cerr << "InputCSV: cannot read mac_mobile.\n" ;
|
||||
return *current_request ;
|
||||
return false ;
|
||||
}
|
||||
PosUtil::to_upper(mac_mobile) ;
|
||||
|
||||
if (! Configuration::bool_value("positioning.accept-new-mobiles") &&
|
||||
! Stock::mobile_exists(mac_mobile))
|
||||
return *current_request ;
|
||||
return false ;
|
||||
|
||||
const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ;
|
||||
current_request->set_mobile(&mobile) ;
|
||||
|
@ -59,11 +53,10 @@ const Request& InputCSV::get_next_request()
|
|||
uint16_t type_r ;
|
||||
if (! file.read_field(type_r))
|
||||
{
|
||||
// Wrong number of fields: blank current request
|
||||
current_request->clear() ;
|
||||
// Wrong number of fields
|
||||
if (Configuration::is_configured("verbose"))
|
||||
cerr << "InputCSV: cannot read type.\n" ;
|
||||
return *current_request ;
|
||||
return false ;
|
||||
}
|
||||
type = type_r ;
|
||||
current_request->set_type(type) ;
|
||||
|
@ -72,11 +65,10 @@ const Request& InputCSV::get_next_request()
|
|||
Timestamp timestamp ;
|
||||
if (! file.read_timestamp(timestamp))
|
||||
{
|
||||
// Wrong number of fields: blank current request
|
||||
current_request->clear() ;
|
||||
// Wrong number of fields
|
||||
if (Configuration::is_configured("verbose"))
|
||||
cerr << "InputCSV: cannot read timestamp.\n" ;
|
||||
return *current_request ;
|
||||
return false ;
|
||||
}
|
||||
current_request->set_time_sent(timestamp) ;
|
||||
|
||||
|
@ -84,11 +76,10 @@ const Request& InputCSV::get_next_request()
|
|||
Point3D position ;
|
||||
if (! file.read_point3d(position))
|
||||
{
|
||||
// Wrong number of fields: blank current request
|
||||
current_request->clear() ;
|
||||
// Wrong number of fields
|
||||
if (Configuration::is_configured("verbose"))
|
||||
cerr << "InputCSV: cannot read coordinates.\n" ;
|
||||
return *current_request ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Read direction field
|
||||
|
@ -96,11 +87,10 @@ const Request& InputCSV::get_next_request()
|
|||
int direction_int ;
|
||||
if (! file.read_field(direction_int))
|
||||
{
|
||||
// Wrong number of fields: blank current request
|
||||
current_request->clear() ;
|
||||
// Wrong number of fields
|
||||
if (Configuration::is_configured("verbose"))
|
||||
cerr << "InputCSV: cannot read direction.\n" ;
|
||||
return *current_request ;
|
||||
return false ;
|
||||
}
|
||||
if (direction_int != 0)
|
||||
direction = direction_int ;
|
||||
|
@ -114,11 +104,10 @@ const Request& InputCSV::get_next_request()
|
|||
int ss ;
|
||||
if (! file.read_field(ss))
|
||||
{
|
||||
// Wrong number of fields: blank current request
|
||||
current_request->clear() ;
|
||||
// Wrong number of fields
|
||||
if (Configuration::is_configured("verbose"))
|
||||
cerr << "InputCSV: cannot read mac_ap.\n" ;
|
||||
return *current_request ;
|
||||
return false ;
|
||||
}
|
||||
PosUtil::to_upper(mac_ap) ;
|
||||
|
||||
|
@ -131,26 +120,11 @@ const Request& InputCSV::get_next_request()
|
|||
measurements[mac_ap].add_ss(ss) ;
|
||||
}
|
||||
if (measurements.empty())
|
||||
{
|
||||
current_request->clear() ;
|
||||
return *current_request ;
|
||||
}
|
||||
return false ;
|
||||
current_request->set_measurements(measurements) ;
|
||||
|
||||
// Calibration request?
|
||||
if (type == OWL_REQUEST_CALIBRATION ||
|
||||
type == OWL_REQUEST_AUTOCALIBRATION)
|
||||
{
|
||||
const ReferencePoint &reference_point =
|
||||
Stock::find_create_reference_point(position) ;
|
||||
current_request_to_calibration_request(&reference_point,
|
||||
direction, type) ;
|
||||
}
|
||||
fill_calibration_request_data(mac_mobile, position, direction, type) ;
|
||||
|
||||
// We set the real coordinates (if found) only for non-calibration
|
||||
// requests
|
||||
else if (position)
|
||||
current_request->set_real_position(position) ;
|
||||
|
||||
return *current_request ;
|
||||
return true ;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,12 @@ class InputCSV: public InputMedium
|
|||
protected:
|
||||
CSVFileReader file ;
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
/// Reads data & fills the current request
|
||||
bool fill_current_request(void) ;
|
||||
//@}
|
||||
|
||||
public:
|
||||
InputCSV(const std::string &filename):
|
||||
file(filename) {}
|
||||
|
@ -28,12 +34,6 @@ public:
|
|||
bool eof(void) const ;
|
||||
//@}
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
/// Reads the next request
|
||||
const Request& get_next_request(void) ;
|
||||
//@}
|
||||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
operator bool(void) const ;
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#include "inputmedium.hh"
|
||||
#include "calibrationrequest.hh"
|
||||
#include "stock.hh"
|
||||
#include "configuration.hh"
|
||||
#include "posexcept.hh"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
|
||||
|
@ -23,6 +28,116 @@ InputMedium::~InputMedium()
|
|||
/* *** Operations *** */
|
||||
|
||||
|
||||
/**
|
||||
* Reads a Request, increments current_line_nb, updates #current_request
|
||||
* and returns it.
|
||||
*
|
||||
* The input medium should be ready to be read before precessing
|
||||
* requests; otherwise, #current_request is \link Request::clear()
|
||||
* cleared\endlink and a blank Request is returned.
|
||||
*
|
||||
* @return The Request read, or an empty Request in case of error or
|
||||
* EOF (note that when casted in bool, an empty Request is \em false,
|
||||
* see Request::operator bool()).
|
||||
*/
|
||||
const Request& InputMedium::get_next_request()
|
||||
{
|
||||
clear_current_request() ;
|
||||
|
||||
if (! fill_current_request())
|
||||
{
|
||||
clear_current_request() ;
|
||||
return *current_request ;
|
||||
}
|
||||
|
||||
return *current_request ;
|
||||
}
|
||||
|
||||
|
||||
void InputMedium::clear_current_request()
|
||||
{
|
||||
if (dynamic_cast<CalibrationRequest*>(current_request) == NULL)
|
||||
current_request->clear() ;
|
||||
else
|
||||
{
|
||||
delete current_request ;
|
||||
current_request = NULL ;
|
||||
current_request = new Request() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The \em position argument can be changed by this function.
|
||||
*/
|
||||
void InputMedium::
|
||||
fill_calibration_request_data(const string &mac_mobile, Point3D &position,
|
||||
const Direction &direction, uint8_t type)
|
||||
{
|
||||
// We set the real coordinates (if found) for non-calibration requests
|
||||
if (type != OWL_REQUEST_CALIBRATION &&
|
||||
type != OWL_REQUEST_AUTOCALIBRATION)
|
||||
{
|
||||
if (position)
|
||||
current_request->set_real_position(position) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
if (position)
|
||||
{
|
||||
// Update the AP's coordinates if allowed (and if the mobile is
|
||||
// an AP, of course)
|
||||
if (Configuration::
|
||||
bool_value("positioning.update-ap-coordinates-online"))
|
||||
{
|
||||
if (type == OWL_REQUEST_AUTOCALIBRATION &&
|
||||
Configuration::bool_value("positioning.accept-new-aps"))
|
||||
{
|
||||
AccessPoint &transmitter =
|
||||
const_cast<AccessPoint&>(
|
||||
Stock::find_create_ap(mac_mobile)) ;
|
||||
transmitter.set_coordinates(position) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
AccessPoint &transmitter =
|
||||
const_cast<AccessPoint&>(Stock::get_ap(mac_mobile)) ;
|
||||
transmitter.set_coordinates(position) ;
|
||||
}
|
||||
catch (element_not_found &e)
|
||||
{
|
||||
// The mobile is not an AP or the AP does not exist
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (type == OWL_REQUEST_AUTOCALIBRATION)
|
||||
{
|
||||
// If an autocalibration request does not contain the coordinates
|
||||
// of the AP, we use the current coordinates of the AP as
|
||||
// ReferencePoint.
|
||||
try
|
||||
{
|
||||
AccessPoint &transmitter =
|
||||
const_cast<AccessPoint&>(Stock::get_ap(mac_mobile)) ;
|
||||
position = transmitter.get_coordinates() ;
|
||||
}
|
||||
catch (element_not_found &e)
|
||||
{
|
||||
// The mobile is not an AP or the AP does not exist
|
||||
}
|
||||
}
|
||||
|
||||
const ReferencePoint &reference_point =
|
||||
Stock::find_create_reference_point(position) ;
|
||||
current_request_to_calibration_request(
|
||||
&reference_point, direction, type) ;
|
||||
}
|
||||
|
||||
|
||||
void InputMedium::
|
||||
current_request_to_calibration_request(
|
||||
const ReferencePoint *const reference_point,
|
||||
|
@ -47,16 +162,3 @@ current_request_to_calibration_request(
|
|||
direction, request_type) ;
|
||||
delete tmp ;
|
||||
}
|
||||
|
||||
|
||||
void InputMedium::clear_current_request()
|
||||
{
|
||||
if (dynamic_cast<CalibrationRequest*>(current_request) == NULL)
|
||||
current_request->clear() ;
|
||||
else
|
||||
{
|
||||
delete current_request ;
|
||||
current_request = NULL ;
|
||||
current_request = new Request() ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ class Direction ;
|
|||
|
||||
#include "request.hh"
|
||||
|
||||
#include <string>
|
||||
|
||||
/// Super class of all input media
|
||||
/**
|
||||
* This class Provides an interface for input media, i.e. to read
|
||||
|
@ -18,6 +20,18 @@ protected:
|
|||
/// Number of the current line proceeded
|
||||
unsigned long current_line_nb ;
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
/// Reads data & fills the current request
|
||||
virtual bool fill_current_request(void) = 0 ;
|
||||
/// \brief Checks if the current request is a calibration request and
|
||||
/// if so fills it with additionnal data
|
||||
void fill_calibration_request_data(const std::string &mac_mobile,
|
||||
Point3D &position,
|
||||
const Direction &direction,
|
||||
uint8_t type) ;
|
||||
//@}
|
||||
|
||||
public:
|
||||
InputMedium(void) ;
|
||||
|
||||
|
@ -43,14 +57,7 @@ public:
|
|||
//@{
|
||||
|
||||
/// Reads the next request
|
||||
/**
|
||||
* Reads a Request, increments current_line_nb, updates #current_request
|
||||
* and returns it.
|
||||
* @return The Request read, or an empty Request in case of error or
|
||||
* EOF (note that when casted in bool, an empty Request is \em false,
|
||||
* see Request::operator bool()).
|
||||
*/
|
||||
virtual const Request& get_next_request(void) = 0 ;
|
||||
const Request& get_next_request(void) ;
|
||||
|
||||
/// Converts #current_request into a CalibrationRequest
|
||||
void current_request_to_calibration_request(
|
||||
|
|
|
@ -72,22 +72,16 @@ bool InputUDPSocket::close_socket()
|
|||
|
||||
|
||||
/**
|
||||
* This function reads the next Request in the UDP input socket.
|
||||
* It cannot read calibration requests.
|
||||
* This function fills the current Request from the UDP input socket.
|
||||
*
|
||||
* #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).
|
||||
* @returns \em true if #current_request was correctly filled.
|
||||
* @returns \em false in case of error (socket not opened, bad packet
|
||||
* format).
|
||||
*/
|
||||
const Request& InputUDPSocket::get_next_request()
|
||||
bool InputUDPSocket::fill_current_request()
|
||||
{
|
||||
clear_current_request() ;
|
||||
|
||||
if (eof())
|
||||
return *current_request ;
|
||||
return false ;
|
||||
|
||||
struct sockaddr_in client; // UDP client structure
|
||||
socklen_t client_len = sizeof(client) ; // Size of clients
|
||||
|
@ -98,8 +92,8 @@ const Request& InputUDPSocket::get_next_request()
|
|||
(struct sockaddr *) &client, &client_len) ;
|
||||
if (nread <= 0)
|
||||
{
|
||||
cerr << "No request received!" << endl ;
|
||||
return *current_request ;
|
||||
cerr << "InputUDPSocket: No request received!" << endl ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Endianess conversions
|
||||
|
@ -113,7 +107,7 @@ const Request& InputUDPSocket::get_next_request()
|
|||
|
||||
if (! Configuration::bool_value("positioning.accept-new-mobiles") &&
|
||||
! Stock::mobile_exists(mac_mobile))
|
||||
return *current_request ;
|
||||
return false ;
|
||||
|
||||
const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ;
|
||||
current_request->set_mobile(&mobile) ;
|
||||
|
@ -139,8 +133,7 @@ const Request& InputUDPSocket::get_next_request()
|
|||
if (nread <= 0)
|
||||
{
|
||||
cerr << "No request info received!" << endl ;
|
||||
current_request->clear() ;
|
||||
return *current_request ;
|
||||
return false ;
|
||||
}
|
||||
string mac_ap(
|
||||
owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes)) ;
|
||||
|
@ -156,47 +149,12 @@ const Request& InputUDPSocket::get_next_request()
|
|||
(request_info.antenna_signal_dbm)) ;
|
||||
}
|
||||
if (measurements.empty())
|
||||
{
|
||||
current_request->clear() ;
|
||||
return *current_request ;
|
||||
}
|
||||
return false ;
|
||||
current_request->set_measurements(measurements) ;
|
||||
|
||||
// Calibration request?
|
||||
if ((request.type == OWL_REQUEST_CALIBRATION ||
|
||||
request.type == OWL_REQUEST_AUTOCALIBRATION)
|
||||
&&
|
||||
(Configuration::bool_value("positioning.accept-new-aps") ||
|
||||
Stock::ap_exists(mac_mobile)))
|
||||
{
|
||||
AccessPoint &transmitter =
|
||||
const_cast<AccessPoint&>(Stock::find_create_ap(mac_mobile)) ;
|
||||
fill_calibration_request_data(
|
||||
mac_mobile, position, request.direction, request.type) ;
|
||||
|
||||
// If an autocalibration request does not contain the coordinates
|
||||
// of the AP, we use the current coordinates of the AP as
|
||||
// ReferencePoint.
|
||||
if (request.type == OWL_REQUEST_AUTOCALIBRATION && ! position)
|
||||
position = transmitter.get_coordinates() ;
|
||||
|
||||
// Update the AP's coordinates if allowed. A 'false' position
|
||||
// (i.e. 0;0;0) is only set for calibration requests, to avoid
|
||||
// setting the coordinates to 0;0;0 if an autocalibration
|
||||
// request that does not contain the coordinates is received.
|
||||
else if (Configuration::
|
||||
bool_value("positioning.update-ap-coordinates-online"))
|
||||
transmitter.set_coordinates(position) ;
|
||||
|
||||
const ReferencePoint &reference_point =
|
||||
Stock::find_create_reference_point(position) ;
|
||||
current_request_to_calibration_request(&reference_point,
|
||||
Direction(request.direction),
|
||||
request.type) ;
|
||||
}
|
||||
|
||||
// We set the real coordinates (if found) only for non-calibration
|
||||
// requests
|
||||
else if (position)
|
||||
current_request->set_real_position(position) ;
|
||||
|
||||
return *current_request ;
|
||||
return true ;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,15 @@ protected:
|
|||
//@{
|
||||
/// Initialises the socket
|
||||
bool init_socket(void) ;
|
||||
/// Reads data & fills the current request
|
||||
/**
|
||||
* This function fills the current Request from the data read from
|
||||
* the input medium.
|
||||
*
|
||||
* @returns \em true if #current_request was correctly filled.
|
||||
* @returns \em false in case of error.
|
||||
*/
|
||||
bool fill_current_request(void) ;
|
||||
//@}
|
||||
|
||||
public:
|
||||
|
@ -29,8 +38,6 @@ public:
|
|||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
/// Reads the next request
|
||||
const Request& get_next_request(void) ;
|
||||
/// Closes the socket
|
||||
bool close_socket(void) ;
|
||||
//@}
|
||||
|
|
|
@ -124,7 +124,7 @@ void Measurement::update_average_ss()
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Measurement& Measurement::operator=(const Measurement &m)
|
||||
Measurement& Measurement::operator=(const Measurement &m)
|
||||
{
|
||||
if (this == &m)
|
||||
return *this ;
|
||||
|
|
|
@ -68,7 +68,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Measurement& operator=(const Measurement &m) ;
|
||||
Measurement& operator=(const Measurement &m) ;
|
||||
bool operator==(const Measurement &m) const ;
|
||||
bool operator!=(const Measurement &m) const ;
|
||||
operator bool(void) const ;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Mobile& Mobile::operator=(const Mobile &m)
|
||||
Mobile& Mobile::operator=(const Mobile &m)
|
||||
{
|
||||
if (this == &m)
|
||||
return *this ;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Mobile& operator=(const Mobile &m) ;
|
||||
Mobile& operator=(const Mobile &m) ;
|
||||
bool operator==(const Mobile &m) const ;
|
||||
bool operator!=(const Mobile &m) const ;
|
||||
//@}
|
||||
|
|
|
@ -18,16 +18,16 @@ MultilaterationAlgorithm::MultilaterationAlgorithm():
|
|||
// Will be changed when other multilateration methods will be
|
||||
// implemented.
|
||||
|
||||
if (! Configuration::is_configured("positioning.minmax-start") ||
|
||||
! Configuration::is_configured("positioning.minmax-stop"))
|
||||
if (! Configuration::is_configured("positioning.area-start") ||
|
||||
! Configuration::is_configured("positioning.area-stop"))
|
||||
throw missing_configuration(
|
||||
"You want to use MinMax, but either positioning.minmax-start or"
|
||||
" positioning.minmax-stop is not defined!") ;
|
||||
"You want to use MinMax, but either positioning.area-start or"
|
||||
" positioning.area-stop is not defined!") ;
|
||||
|
||||
Point3D minmax_start(
|
||||
Configuration::string_value("positioning.minmax-start")) ;
|
||||
Configuration::string_value("positioning.area-start")) ;
|
||||
Point3D minmax_stop(
|
||||
Configuration::string_value("positioning.minmax-stop")) ;
|
||||
Configuration::string_value("positioning.area-stop")) ;
|
||||
|
||||
multilateration_method = new MinMax(minmax_start, minmax_stop) ;
|
||||
}
|
||||
|
@ -47,19 +47,15 @@ double MultilaterationAlgorithm::
|
|||
make_constant_term(const Measurement &measurement)
|
||||
{
|
||||
assert(request) ;
|
||||
assert(request->get_mobile()) ;
|
||||
const Mobile *mobile = request->get_mobile() ;
|
||||
assert(mobile) ;
|
||||
const AccessPoint *ap = measurement.get_ap() ;
|
||||
assert(ap) ;
|
||||
|
||||
return
|
||||
ap->get_trx_power() +
|
||||
ap->get_antenna_gain() +
|
||||
20 * log10(
|
||||
static_cast<double>(PosUtil::LIGHT_SPEED) /
|
||||
ap->get_frequency() /
|
||||
(4 * M_PI)
|
||||
) +
|
||||
request->get_mobile()->get_antenna_gain() ;
|
||||
ap->friis_constant_term() +
|
||||
mobile->get_antenna_gain() +
|
||||
mobile->get_trx_power() ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
/// Writes results to a CSV file
|
||||
/**
|
||||
* CSV format is:
|
||||
* Mobile_MAC;Timestamp;Algorithm1;X;Y;Z;…;AlgorithmN;X;Y;Z
|
||||
* The CSV format is documented in ResultList::to_csv().
|
||||
*/
|
||||
class OutputCSV: public OutputMedium
|
||||
{
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#include "outputnetworksocket.hh"
|
||||
#include "resultlist.hh"
|
||||
#include "result.hh"
|
||||
#include "posexcept.hh"
|
||||
|
||||
#include <cstdio> // For perror()
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
|
||||
/* *** Constructors *** */
|
||||
|
||||
|
||||
OutputNetworkSocket::~OutputNetworkSocket()
|
||||
{
|
||||
close_socket() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Operations *** */
|
||||
|
||||
|
||||
/**
|
||||
* 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 OutputNetworkSocket::close_socket()
|
||||
{
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
if (close(sockfd))
|
||||
{
|
||||
perror("Cannot close network socket") ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
sockfd = -1 ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
void OutputNetworkSocket::write(const Result &result)
|
||||
{
|
||||
send_data(result.to_csv()) ;
|
||||
}
|
||||
|
||||
|
||||
void OutputNetworkSocket::write(const ResultList &results)
|
||||
{
|
||||
if (! results.empty())
|
||||
send_data(results.to_csv()) ;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#ifndef _OWLPS_POSITIONING_OUTPUTNETWORKSOCKET_HH_
|
||||
#define _OWLPS_POSITIONING_OUTPUTNETWORKSOCKET_HH_
|
||||
|
||||
#include "outputmedium.hh"
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h> // <cstdint> is not C++ 98 compliant
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/// Parent class for all output media that use network sockets
|
||||
class OutputNetworkSocket: 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
|
||||
/**
|
||||
* You are required to call this function from the constructor of any
|
||||
* derived class.
|
||||
*/
|
||||
virtual bool init_socket(void) = 0 ;
|
||||
/// Sends a string through the socket
|
||||
virtual bool send_data(const std::string &data) const = 0 ;
|
||||
//@}
|
||||
|
||||
public:
|
||||
OutputNetworkSocket(const std::string &_remote_host,
|
||||
const uint_fast16_t _remote_port):
|
||||
sockfd(-1), remote_host(_remote_host), remote_port(_remote_port) {}
|
||||
~OutputNetworkSocket(void) ;
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
/// Sends a list of results through the socket
|
||||
void write(const ResultList &results) ;
|
||||
/// Sends a single result through the socket
|
||||
void write(const Result &result) ;
|
||||
/// Closes the socket
|
||||
bool close_socket(void) ;
|
||||
//@}
|
||||
} ;
|
||||
|
||||
#endif // _OWLPS_POSITIONING_OUTPUTNETWORKSOCKET_HH_
|
|
@ -17,19 +17,13 @@ using namespace std ;
|
|||
/* *** Constructors *** */
|
||||
|
||||
|
||||
OutputTCPSocketEvAAL::OutputTCPSocketEvAAL(
|
||||
const string &_remote_host,
|
||||
const uint_fast16_t _remote_port):
|
||||
remote_host(_remote_host), remote_port(_remote_port)
|
||||
OutputTCPSocketEvAAL::
|
||||
OutputTCPSocketEvAAL(const string &_remote_host,
|
||||
const uint_fast16_t _remote_port):
|
||||
OutputNetworkSocket(_remote_host, _remote_port)
|
||||
{
|
||||
if (! init_socket())
|
||||
throw error_opening_output_file("TCP socket") ;
|
||||
}
|
||||
|
||||
|
||||
OutputTCPSocketEvAAL::~OutputTCPSocketEvAAL()
|
||||
{
|
||||
close_socket() ;
|
||||
throw error_opening_output_file("TCP socket (EvAAL)") ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,31 +64,6 @@ bool OutputTCPSocketEvAAL::init_socket()
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param results Must contain only one element, since the EvAAL format
|
||||
* accepts only one algorithm result.
|
||||
|
@ -128,7 +97,7 @@ void OutputTCPSocketEvAAL::write(const Result &result)
|
|||
int OutputTCPSocketEvAAL::
|
||||
area_of_interest_number(const Point3D &position) const
|
||||
{
|
||||
const Area *area = Stock::in_which_area_is(position) ;
|
||||
const Area *const area = Stock::in_which_area_is(position) ;
|
||||
if (area == NULL)
|
||||
return 0 ;
|
||||
|
||||
|
@ -157,7 +126,7 @@ 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") ;
|
||||
perror("Error sending result data through the TCPEvAAL socket") ;
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
|
|
|
@ -3,27 +3,16 @@
|
|||
|
||||
class Point3D ;
|
||||
|
||||
#include "outputmedium.hh"
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h> // <cstdint> is not C++ 98 compliant
|
||||
#include <arpa/inet.h>
|
||||
#include "outputnetworksocket.hh"
|
||||
|
||||
/// 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
|
||||
class OutputTCPSocketEvAAL: public OutputNetworkSocket
|
||||
{
|
||||
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
|
||||
|
@ -37,16 +26,15 @@ protected:
|
|||
public:
|
||||
OutputTCPSocketEvAAL(const std::string &_remote_host,
|
||||
const uint_fast16_t _remote_port) ;
|
||||
~OutputTCPSocketEvAAL(void) ;
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
/// Sends a list of results through the socket
|
||||
void write(const ResultList &results) ;
|
||||
/// Sends a single result through the socket
|
||||
void write(const Result &result) ;
|
||||
/// Get the area of interest number from the position
|
||||
int area_of_interest_number(const Point3D &position) const ;
|
||||
/// Closes the socket
|
||||
bool close_socket(void) ;
|
||||
//@}
|
||||
} ;
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "outputudpsocket.hh"
|
||||
#include "request.hh"
|
||||
#include "resultlist.hh"
|
||||
#include "result.hh"
|
||||
#include "posexcept.hh"
|
||||
|
||||
#include <owlps.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <cstdio> // For perror()
|
||||
|
||||
using namespace std ;
|
||||
|
@ -17,17 +17,10 @@ using namespace std ;
|
|||
|
||||
OutputUDPSocket::OutputUDPSocket(const string &_remote_host,
|
||||
const uint_fast16_t _remote_port):
|
||||
remote_host(_remote_host), remote_port(_remote_port)
|
||||
OutputNetworkSocket(_remote_host, _remote_port)
|
||||
{
|
||||
if (! init_socket())
|
||||
throw error_opening_output_file("UDP socket") ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
OutputUDPSocket::~OutputUDPSocket()
|
||||
{
|
||||
close_socket() ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -47,52 +40,18 @@ bool OutputUDPSocket::init_socket()
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 OutputUDPSocket::close_socket()
|
||||
{
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
if (close(sockfd))
|
||||
{
|
||||
perror("Cannot close UDP socket") ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
sockfd = -1 ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
void OutputUDPSocket::write(const Result &result)
|
||||
{
|
||||
send_data(result.to_csv()) ;
|
||||
}
|
||||
|
||||
|
||||
void OutputUDPSocket::write(const ResultList &results)
|
||||
{
|
||||
if (! results.empty())
|
||||
send_data(results.to_csv()) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends the text buffer 'data'.
|
||||
*/
|
||||
void OutputUDPSocket::send_data(const string &data)
|
||||
bool OutputUDPSocket::send_data(const string &data) const
|
||||
{
|
||||
ssize_t nsent = sendto(sockfd, data.c_str(), data.size(), 0,
|
||||
(struct sockaddr *) &server_info,
|
||||
sizeof(server_info)) ;
|
||||
if (nsent != static_cast<ssize_t>(data.size()))
|
||||
perror("Error sending result data") ;
|
||||
{
|
||||
perror("Error sending result data through the UDP socket") ;
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
|
|
@ -1,46 +1,28 @@
|
|||
#ifndef _OWLPS_POSITIONING_OUTPUTUDPSOCKET_HH_
|
||||
#define _OWLPS_POSITIONING_OUTPUTUDPSOCKET_HH_
|
||||
|
||||
#include "outputmedium.hh"
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h> // <cstdint> is not C++ 98 compliant
|
||||
#include <arpa/inet.h>
|
||||
#include "outputnetworksocket.hh"
|
||||
|
||||
/// Sends results to a remote host by UDP
|
||||
/**
|
||||
* The results are sent through an UDP socket as a CSV string value. The
|
||||
* format used is the same as in OutputCSV.
|
||||
* The results are sent through an UDP socket as a CSV string value.
|
||||
* The format used is the same as in OutputCSV, and is documented in
|
||||
* ResultList::to_csv().
|
||||
*/
|
||||
class OutputUDPSocket: public OutputMedium
|
||||
class OutputUDPSocket: public OutputNetworkSocket
|
||||
{
|
||||
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) ;
|
||||
void send_data(const std::string &data) ;
|
||||
/// Sends a string through the socket
|
||||
bool send_data(const std::string &data) const ;
|
||||
//@}
|
||||
|
||||
public:
|
||||
OutputUDPSocket(const std::string &_remote_ip,
|
||||
const uint_fast16_t _port) ;
|
||||
~OutputUDPSocket(void) ;
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
void write(const Result &result) ;
|
||||
void write(const ResultList &results) ;
|
||||
/// Closes the socket
|
||||
bool close_socket(void) ;
|
||||
//@}
|
||||
OutputUDPSocket(const std::string &_remote_host,
|
||||
const uint_fast16_t _remote_port) ;
|
||||
} ;
|
||||
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ double Point3D::angle(const Point3D &b, const Point3D &c) const
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Point3D& Point3D::operator=(const Point3D &source)
|
||||
Point3D& Point3D::operator=(const Point3D &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Point3D& operator=(const Point3D &source) ;
|
||||
Point3D& operator=(const Point3D &source) ;
|
||||
bool operator==(const Point3D &source) const ;
|
||||
bool operator!=(const Point3D &source) const ;
|
||||
bool operator<(const Point3D &source) const ;
|
||||
|
|
|
@ -61,7 +61,12 @@ void Positioning::initialise_algorithms()
|
|||
|
||||
else if (*i == "FBCM")
|
||||
{
|
||||
Stock::update_all_friis_indexes() ;
|
||||
// Generate the Friis indexes only if the autocalibration is
|
||||
// not activated (if it is, Friis indexes will be regenerated
|
||||
// each time FBCM wants to computes a position)
|
||||
if (! Configuration::
|
||||
bool_value("positioning.generate-reference-points"))
|
||||
Stock::update_all_friis_indexes() ;
|
||||
algorithms.push_back(new FBCM) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -204,13 +204,7 @@ float ReferencePoint::
|
|||
friis_index_for_ap(const string &ap_mac) const
|
||||
{
|
||||
const AccessPoint &ap = Stock::get_ap(ap_mac) ;
|
||||
|
||||
double ap_freq = ap.get_frequency() ;
|
||||
double const_term =
|
||||
ap.get_antenna_gain()
|
||||
- 20 * log10(4 * M_PI)
|
||||
+ 20 * log10(PosUtil::LIGHT_SPEED / ap_freq)
|
||||
+ ap.get_trx_power() ;
|
||||
double const_term = ap.friis_constant_term() ;
|
||||
|
||||
int nb_friis_idx = 0 ;
|
||||
double friis_idx_sum =
|
||||
|
@ -258,8 +252,10 @@ float ReferencePoint::friis_indexes_for_ap(
|
|||
assert((*request)->get_mobile()) ;
|
||||
float mobile_gain =
|
||||
(*request)->get_mobile()->get_antenna_gain() ;
|
||||
float mobile_pow =
|
||||
(*request)->get_mobile()->get_trx_power() ;
|
||||
friis_idx_sum +=
|
||||
(const_term + mobile_gain - ss)
|
||||
(const_term + mobile_gain + mobile_pow - ss)
|
||||
/ (10 * log10(distance)) ;
|
||||
++nb_indexes ;
|
||||
}
|
||||
|
@ -272,8 +268,7 @@ float ReferencePoint::friis_indexes_for_ap(
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const ReferencePoint& ReferencePoint::
|
||||
operator=(const ReferencePoint &source)
|
||||
ReferencePoint& ReferencePoint::operator=(const ReferencePoint &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const ReferencePoint& operator=(const ReferencePoint &source) ;
|
||||
ReferencePoint& operator=(const ReferencePoint &source) ;
|
||||
bool operator==(const ReferencePoint &source) const ;
|
||||
bool operator!=(const ReferencePoint &source) const ;
|
||||
//@}
|
||||
|
|
|
@ -79,7 +79,7 @@ float Request::ss_square_distance(const Request &source) const
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Request& Request::operator=(const Request &source)
|
||||
Request& Request::operator=(const Request &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
|
|
@ -94,7 +94,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Request& operator=(const Request &source) ;
|
||||
Request& operator=(const Request &source) ;
|
||||
bool operator==(const Request &comp) const ;
|
||||
bool operator!=(const Request &comp) const ;
|
||||
operator bool(void) const ;
|
||||
|
|
|
@ -50,7 +50,7 @@ void Result::compute_error(const Point3D &real_position)
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Result& Result::operator=(const Result &source)
|
||||
Result& Result::operator=(const Result &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
@ -76,7 +76,12 @@ bool Result::operator==(const Result &source) const
|
|||
|
||||
|
||||
/**
|
||||
* @return The result as a CSV string, \em without trailing '\n'.
|
||||
* This function creates a CSV string from the Result's data.
|
||||
*
|
||||
* The format used is the following:
|
||||
* Algorithm_name;X;Y;Z;Error;Area_name
|
||||
*
|
||||
* @return The result as a CSV string, \em without a trailing '\\n'.
|
||||
*/
|
||||
const string Result::to_csv() const
|
||||
{
|
||||
|
@ -87,8 +92,12 @@ const string Result::to_csv() const
|
|||
<< ';' << position.get_x()
|
||||
<< ';' << position.get_y()
|
||||
<< ';' << position.get_z()
|
||||
<< ';' << "Error"
|
||||
<< ';' << error ;
|
||||
<< ';' << error
|
||||
<< ';' ;
|
||||
|
||||
const Area *const area = Stock::in_which_area_is(position) ;
|
||||
if (area != NULL)
|
||||
csv_line << area->get_name() ;
|
||||
|
||||
return csv_line.str() ;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Result& operator=(const Result &source) ;
|
||||
Result& operator=(const Result &source) ;
|
||||
bool operator==(const Result &source) const ;
|
||||
bool operator!=(const Result &source) const ;
|
||||
//@}
|
||||
|
|
|
@ -21,7 +21,7 @@ ResultList::~ResultList()
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const ResultList& ResultList::operator=(const ResultList &source)
|
||||
ResultList& ResultList::operator=(const ResultList &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
@ -46,7 +46,15 @@ bool ResultList::operator==(const ResultList &source) const
|
|||
|
||||
|
||||
/**
|
||||
* @return The results as a CSV string, \em without trailing '\n'.
|
||||
* This function creates a CSV string from the Result's data.
|
||||
*
|
||||
* The format used is the following:
|
||||
* Mobile_MAC;Request_type;Timestamp;[Algorithm_1];…;[Algorithm_n]
|
||||
*
|
||||
* The CSV format for the [Algorithm_i] strings is documented in
|
||||
* Result::to_csv().
|
||||
*
|
||||
* @return The results as a CSV string, \em without a trailing '\\n'.
|
||||
*/
|
||||
const string ResultList::to_csv() const
|
||||
{
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const ResultList& operator=(const ResultList &source) ;
|
||||
ResultList& operator=(const ResultList &source) ;
|
||||
bool operator==(const ResultList &source) const ;
|
||||
bool operator!=(const ResultList &source) const ;
|
||||
//@}
|
||||
|
|
|
@ -87,7 +87,7 @@ const Building& Stock::get_building(const string &name)
|
|||
* @returns A pointer to the first Area in which \em point was found.
|
||||
* @returns NULL if \em point does not belong to any Area.
|
||||
*/
|
||||
const Area* Stock::in_which_area_is(const Point3D point)
|
||||
const Area* Stock::in_which_area_is(const Point3D &point)
|
||||
{
|
||||
for (unordered_map<string, Building>::const_iterator
|
||||
b = buildings.begin() ; b != buildings.end() ; ++b)
|
||||
|
@ -281,12 +281,7 @@ void Stock::update_all_friis_indexes()
|
|||
int nb_friis_idx = 0 ;
|
||||
|
||||
// Compute main general term, independant from scans
|
||||
double ap_freq = ap->second.get_frequency() ;
|
||||
double const_term =
|
||||
ap->second.get_antenna_gain()
|
||||
- 20 * log10(4 * M_PI)
|
||||
+ 20 * log10(PosUtil::LIGHT_SPEED / ap_freq)
|
||||
+ ap->second.get_trx_power() ;
|
||||
double const_term = ap->second.friis_constant_term() ;
|
||||
|
||||
/*
|
||||
* Compute indexes for each ReferencePoint. The Friis index for an
|
||||
|
@ -424,48 +419,12 @@ closest_reference_point(const Request &request)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Each reference point P we want to generate will end-up containing
|
||||
* as many calibration requests as the total number of APs.
|
||||
* For each of these requests, we consider a transmitter TRX (which is
|
||||
* a virtual mobile) and a receiver RX (the current AP).
|
||||
* To generate the signal strength (SS) received in P by RX from TRX,
|
||||
* we first select two reference APs REF1 and REF2. Then, we average
|
||||
* the real measurements REF1->RX and REF2->RX, weighting in function
|
||||
* of the angles REF-RX-TRX and the distance from RX to TRX to compute
|
||||
* the SS.
|
||||
* Hope this is clear enough…
|
||||
*/
|
||||
void Stock::regenerate_reference_points()
|
||||
{
|
||||
assert(! aps.empty()) ;
|
||||
assert(! reference_points.empty()) ;
|
||||
|
||||
/* Delete calibration requests that do not come from the APs */
|
||||
unordered_set<ReferencePoint>::iterator rp = reference_points.begin() ;
|
||||
while (rp != reference_points.end())
|
||||
{
|
||||
ReferencePoint rp_copy(*rp) ;
|
||||
if (rp_copy.delete_generated_requests()) // rp_copy was modified
|
||||
{
|
||||
rp = reference_points.erase(rp) ;
|
||||
// Reinsert the modified copy if it still contains at least
|
||||
// one CalibrationRequest:
|
||||
if (! rp_copy.get_requests().empty())
|
||||
reference_points.insert(rp_copy) ;
|
||||
/* __Note on the above insert__
|
||||
* From the boost::unordered documentation:
|
||||
* "insert is only allowed to invalidate iterators when the
|
||||
* insertion causes the load factor to be greater than or
|
||||
* equal to the maximum load factor."
|
||||
* In our case, we always remove an element prior to insert,
|
||||
* so the load factor will never change; therefore insert()
|
||||
* should be safe here.
|
||||
*/
|
||||
}
|
||||
else // rp_copy was not modified
|
||||
++rp ;
|
||||
}
|
||||
delete_non_ap_calibration_requests() ;
|
||||
|
||||
if (reference_points.size() < 3)
|
||||
{
|
||||
|
@ -477,15 +436,15 @@ void Stock::regenerate_reference_points()
|
|||
}
|
||||
|
||||
/* Generate RPs */
|
||||
if (! Configuration::is_configured("positioning.minmax-start") ||
|
||||
! Configuration::is_configured("positioning.minmax-stop"))
|
||||
if (! Configuration::is_configured("positioning.area-start") ||
|
||||
! Configuration::is_configured("positioning.area-stop"))
|
||||
throw missing_configuration(
|
||||
"You must define the deployment area in order to generate"
|
||||
" reference points.") ;
|
||||
Point3D start(
|
||||
Configuration::string_value("positioning.minmax-start")) ;
|
||||
Configuration::string_value("positioning.area-start")) ;
|
||||
Point3D stop(
|
||||
Configuration::string_value("positioning.minmax-stop")) ;
|
||||
Configuration::string_value("positioning.area-stop")) ;
|
||||
float step_x =
|
||||
Configuration::float_value("positioning.generated-meshing-grain-x") ;
|
||||
float step_y =
|
||||
|
@ -496,150 +455,161 @@ void Stock::regenerate_reference_points()
|
|||
//for (float z = start.get_z() ; z <= stop.get_z() ; z += step_z)
|
||||
{
|
||||
Point3D current_point(x,y,z) ;
|
||||
|
||||
// If the point is the coordinates of an existing AP, we don't
|
||||
// need to generate it
|
||||
if (is_ap_coordinate(current_point))
|
||||
continue ;
|
||||
|
||||
/* Get/create the reference point */
|
||||
const ReferencePoint ¤t_rp =
|
||||
find_create_reference_point(current_point) ;
|
||||
|
||||
/* Create the timestamp */
|
||||
Timestamp time_sent ;
|
||||
time_sent.now() ;
|
||||
|
||||
/* Create the measurement list */
|
||||
unordered_map<string, Measurement> measurements ;
|
||||
|
||||
/* Prepare the virtual mobile */
|
||||
string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ;
|
||||
// The gain and trx power of the mobile will be the average of
|
||||
// those of all the known APs (could be better, probably)
|
||||
double vmob_gain = 0 ;
|
||||
double vmob_pow = 0 ;
|
||||
|
||||
for (unordered_map<string, AccessPoint>::const_iterator
|
||||
rx = aps.begin() ; rx != aps.end() ; ++rx)
|
||||
{
|
||||
/* Update the mobile's attributes */
|
||||
vmob_gain += rx->second.get_antenna_gain() / aps.size() ;
|
||||
vmob_pow += rx->second.get_trx_power() / aps.size() ;
|
||||
|
||||
/* Choose the 2 nearest APs in angle */
|
||||
const Point3D &rx_coord =
|
||||
rx->second.get_coordinates() ;
|
||||
multimap<double,
|
||||
unordered_map<string, AccessPoint>::const_iterator>
|
||||
sorted_angles ;
|
||||
for (unordered_map<string, AccessPoint>::const_iterator
|
||||
ref = aps.begin() ; ref != aps.end() ; ++ref)
|
||||
{
|
||||
if (ref == rx)
|
||||
continue ;
|
||||
const Point3D &ref_coord =
|
||||
ref->second.get_coordinates() ;
|
||||
// Skip the AP if the associated reference point does
|
||||
// not exist yet:
|
||||
if (! reference_point_exists(ref_coord))
|
||||
continue ;
|
||||
double angle =
|
||||
rx_coord.angle(current_point, ref_coord) ;
|
||||
pair<double,
|
||||
unordered_map<string, AccessPoint>::const_iterator>
|
||||
angle_ap(angle, ref) ;
|
||||
sorted_angles.insert(angle_ap) ;
|
||||
}
|
||||
assert(sorted_angles.size() > 1) ;
|
||||
|
||||
/* Compute the angle weight of the 2 reference APs */
|
||||
map<double,
|
||||
unordered_map<string, AccessPoint>::const_iterator>
|
||||
::const_iterator s = sorted_angles.begin() ;
|
||||
// Angle REF1-RX-P
|
||||
double ref1_angle = s->first ;
|
||||
const AccessPoint &ref1 = s->second->second ;
|
||||
++s ;
|
||||
const AccessPoint &ref2 = s->second->second ;
|
||||
|
||||
// Angle REF1-RX-REF2
|
||||
const Point3D &ref1_coord = ref1.get_coordinates() ;
|
||||
const Point3D &ref2_coord = ref2.get_coordinates() ;
|
||||
double reference_angle =
|
||||
rx_coord.angle(ref1_coord, ref2_coord) ;
|
||||
double ref1_percent, ref2_percent ;
|
||||
if (reference_angle == 0)
|
||||
ref1_percent = ref2_percent = 50 ;
|
||||
else
|
||||
{
|
||||
ref1_percent = ref1_angle * 100 / reference_angle ;
|
||||
if (ref1_percent > 100)
|
||||
ref1_percent = 100 ;
|
||||
ref2_percent = 100 - ref1_percent ;
|
||||
}
|
||||
|
||||
/* Compute the SS that would be received from a mobile at
|
||||
* distance of RX-P, in the direction of each reference AP */
|
||||
// Distance RX-P
|
||||
float current_point_dst =
|
||||
rx_coord.distance(current_point) ;
|
||||
// Constants & common data
|
||||
double wavelength =
|
||||
static_cast<double>(PosUtil::LIGHT_SPEED) /
|
||||
rx->second.get_frequency() ;
|
||||
double common_ss =
|
||||
rx->second.get_antenna_gain() +
|
||||
20 * log10(wavelength) -
|
||||
20 * log10(4 * M_PI) ;
|
||||
// SS for REF1
|
||||
const ReferencePoint &ref1_rp =
|
||||
get_reference_point(ref1_coord) ;
|
||||
double friis_index =
|
||||
ref1_rp.friis_index_for_ap(rx->second.get_mac_addr()) ;
|
||||
double ref1_ss =
|
||||
common_ss +
|
||||
ref1.get_trx_power() +
|
||||
ref1.get_antenna_gain() -
|
||||
10 * friis_index * log10(current_point_dst) ;
|
||||
// SS for REF2
|
||||
const ReferencePoint &ref2_rp =
|
||||
get_reference_point(ref2_coord) ;
|
||||
friis_index =
|
||||
ref2_rp.friis_index_for_ap(rx->second.get_mac_addr()) ;
|
||||
double ref2_ss =
|
||||
common_ss +
|
||||
ref2.get_trx_power() +
|
||||
ref2.get_antenna_gain() -
|
||||
10 * friis_index * log10(current_point_dst) ;
|
||||
|
||||
/* Compute the SS */
|
||||
ref1_ss = ref1_ss * ref1_percent / 100 ;
|
||||
ref2_ss = ref2_ss * ref2_percent / 100 ;
|
||||
double rx_ss = ref1_ss + ref2_ss ;
|
||||
|
||||
/* Create the measurement, add it to the list */
|
||||
Measurement m(&rx->second) ;
|
||||
m.add_ss(rx_ss) ;
|
||||
measurements[rx->second.get_mac_addr()] = m ;
|
||||
}
|
||||
|
||||
/* Create the virtual mobile */
|
||||
Mobile vmob("", vmob_mac, vmob_gain, vmob_pow) ;
|
||||
const Mobile &mobile = find_create_mobile(vmob) ;
|
||||
|
||||
/* Create the calibration request */
|
||||
CalibrationRequest cr(OWL_REQUEST_GENERATED) ;
|
||||
cr.set_time_sent(time_sent) ;
|
||||
cr.set_mobile(&mobile) ;
|
||||
cr.set_measurements(measurements) ;
|
||||
cr.set_reference_point(¤t_rp) ;
|
||||
|
||||
store_calibration_request(cr) ;
|
||||
generate_reference_point(current_point) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The reference point P we want to generate will end-up containing
|
||||
* as many calibration requests as the total number of APs.
|
||||
* For each of these requests, we consider a transmitter TRX (which is
|
||||
* a virtual mobile) and a receiver RX (the current AP).
|
||||
* To generate the signal strength (SS) received in P by RX from TRX,
|
||||
* we first select two reference APs REF1 and REF2. Then, we average
|
||||
* the real measurements REF1->RX and REF2->RX, weighting in function
|
||||
* of the angles REF-RX-TRX and the distance from RX to TRX to compute
|
||||
* the SS.
|
||||
* Hope this is clear enough…
|
||||
*/
|
||||
void Stock::generate_reference_point(const Point3D &point)
|
||||
{
|
||||
// If the point is the coordinates of an existing AP, we don't
|
||||
// need to generate it
|
||||
if (is_ap_coordinate(point))
|
||||
return ;
|
||||
|
||||
/* Get/create the reference point */
|
||||
const ReferencePoint ¤t_rp =
|
||||
find_create_reference_point(point) ;
|
||||
|
||||
/* Create the timestamp */
|
||||
Timestamp time_sent ;
|
||||
time_sent.now() ;
|
||||
|
||||
/* Create the measurement list */
|
||||
unordered_map<string, Measurement> measurements ;
|
||||
|
||||
/* Prepare the virtual mobile */
|
||||
string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ;
|
||||
// The gain and trx power of the mobile will be the average of
|
||||
// those of all the known APs (could be better, probably)
|
||||
double vmob_gain = 0 ;
|
||||
double vmob_pow = 0 ;
|
||||
|
||||
for (unordered_map<string, AccessPoint>::const_iterator
|
||||
rx = aps.begin() ; rx != aps.end() ; ++rx)
|
||||
{
|
||||
/* Update the mobile's attributes */
|
||||
vmob_gain += rx->second.get_antenna_gain() / aps.size() ;
|
||||
vmob_pow += rx->second.get_trx_power() / aps.size() ;
|
||||
|
||||
/* Choose the 2 nearest APs in angle */
|
||||
const Point3D &rx_coord =
|
||||
rx->second.get_coordinates() ;
|
||||
multimap<double,
|
||||
unordered_map<string, AccessPoint>::const_iterator>
|
||||
sorted_angles ;
|
||||
for (unordered_map<string, AccessPoint>::const_iterator
|
||||
ref = aps.begin() ; ref != aps.end() ; ++ref)
|
||||
{
|
||||
if (ref == rx)
|
||||
continue ;
|
||||
const Point3D &ref_coord =
|
||||
ref->second.get_coordinates() ;
|
||||
// Skip the AP if the associated reference point does
|
||||
// not exist yet:
|
||||
if (! reference_point_exists(ref_coord))
|
||||
continue ;
|
||||
double angle =
|
||||
rx_coord.angle(point, ref_coord) ;
|
||||
pair<double,
|
||||
unordered_map<string, AccessPoint>::const_iterator>
|
||||
angle_ap(angle, ref) ;
|
||||
sorted_angles.insert(angle_ap) ;
|
||||
}
|
||||
assert(sorted_angles.size() > 1) ;
|
||||
|
||||
/* Compute the angle weight of the 2 reference APs */
|
||||
map<double,
|
||||
unordered_map<string, AccessPoint>::const_iterator>
|
||||
::const_iterator s = sorted_angles.begin() ;
|
||||
// Angle REF1-RX-P
|
||||
double ref1_angle = s->first ;
|
||||
const AccessPoint &ref1 = s->second->second ;
|
||||
++s ;
|
||||
const AccessPoint &ref2 = s->second->second ;
|
||||
|
||||
// Angle REF1-RX-REF2
|
||||
const Point3D &ref1_coord = ref1.get_coordinates() ;
|
||||
const Point3D &ref2_coord = ref2.get_coordinates() ;
|
||||
double reference_angle =
|
||||
rx_coord.angle(ref1_coord, ref2_coord) ;
|
||||
double ref1_percent, ref2_percent ;
|
||||
if (reference_angle == 0)
|
||||
ref1_percent = ref2_percent = 50 ;
|
||||
else
|
||||
{
|
||||
ref1_percent = ref1_angle * 100 / reference_angle ;
|
||||
if (ref1_percent > 100)
|
||||
ref1_percent = 100 ;
|
||||
ref2_percent = 100 - ref1_percent ;
|
||||
}
|
||||
|
||||
/* Compute the SS that would be received from a mobile at
|
||||
* distance of RX-P, in the direction of each reference AP */
|
||||
// Distance RX-P
|
||||
float point_dst =
|
||||
rx_coord.distance(point) ;
|
||||
// Constant term
|
||||
double common_ss = rx->second.friis_constant_term() ;
|
||||
// SS for REF1
|
||||
const ReferencePoint &ref1_rp =
|
||||
get_reference_point(ref1_coord) ;
|
||||
double friis_index =
|
||||
ref1_rp.friis_index_for_ap(rx->second.get_mac_addr()) ;
|
||||
double ref1_ss =
|
||||
common_ss +
|
||||
ref1.get_trx_power() +
|
||||
ref1.get_antenna_gain() -
|
||||
10 * friis_index * log10(point_dst) ;
|
||||
// SS for REF2
|
||||
const ReferencePoint &ref2_rp =
|
||||
get_reference_point(ref2_coord) ;
|
||||
friis_index =
|
||||
ref2_rp.friis_index_for_ap(rx->second.get_mac_addr()) ;
|
||||
double ref2_ss =
|
||||
common_ss +
|
||||
ref2.get_trx_power() +
|
||||
ref2.get_antenna_gain() -
|
||||
10 * friis_index * log10(point_dst) ;
|
||||
|
||||
/* Compute the SS */
|
||||
ref1_ss = ref1_ss * ref1_percent / 100 ;
|
||||
ref2_ss = ref2_ss * ref2_percent / 100 ;
|
||||
double rx_ss = ref1_ss + ref2_ss ;
|
||||
|
||||
/* Create the measurement, add it to the list */
|
||||
Measurement m(&rx->second) ;
|
||||
m.add_ss(rx_ss) ;
|
||||
measurements[rx->second.get_mac_addr()] = m ;
|
||||
}
|
||||
|
||||
/* Create the virtual mobile */
|
||||
Mobile vmob("", vmob_mac, vmob_gain, vmob_pow) ;
|
||||
const Mobile &mobile = find_create_mobile(vmob) ;
|
||||
|
||||
/* Create the calibration request */
|
||||
CalibrationRequest cr(OWL_REQUEST_GENERATED) ;
|
||||
cr.set_time_sent(time_sent) ;
|
||||
cr.set_mobile(&mobile) ;
|
||||
cr.set_measurements(measurements) ;
|
||||
cr.set_reference_point(¤t_rp) ;
|
||||
|
||||
store_calibration_request(cr) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** CalibrationRequest operations *** */
|
||||
|
||||
|
@ -729,3 +699,32 @@ closest_calibration_request(const Request &request)
|
|||
|
||||
return *closest ;
|
||||
}
|
||||
|
||||
|
||||
void Stock::delete_non_ap_calibration_requests()
|
||||
{
|
||||
unordered_set<ReferencePoint>::iterator rp = reference_points.begin() ;
|
||||
while (rp != reference_points.end())
|
||||
{
|
||||
ReferencePoint rp_copy(*rp) ;
|
||||
if (rp_copy.delete_generated_requests()) // rp_copy was modified
|
||||
{
|
||||
rp = reference_points.erase(rp) ;
|
||||
// Reinsert the modified copy if it still contains at least
|
||||
// one CalibrationRequest:
|
||||
if (! rp_copy.get_requests().empty())
|
||||
reference_points.insert(rp_copy) ;
|
||||
/* __Note on the above insert__
|
||||
* From the boost::unordered documentation:
|
||||
* "insert is only allowed to invalidate iterators when the
|
||||
* insertion causes the load factor to be greater than or
|
||||
* equal to the maximum load factor."
|
||||
* In our case, we always remove an element prior to insert,
|
||||
* so the load factor will never change; therefore insert()
|
||||
* should be safe here.
|
||||
*/
|
||||
}
|
||||
else // rp_copy was not modified
|
||||
++rp ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,18 @@ private:
|
|||
/// List of known CalibrationRequest
|
||||
static std::tr1::unordered_set<CalibrationRequest> calibration_requests ;
|
||||
|
||||
/** @name ReferencePoint operations */
|
||||
//@{
|
||||
/// Generates a single reference point
|
||||
static void generate_reference_point(const Point3D &point) ;
|
||||
//@}
|
||||
|
||||
/** @name CalibrationRequest operations */
|
||||
//@{
|
||||
/// Delete calibration requests that do not come from the APs
|
||||
static void delete_non_ap_calibration_requests(void) ;
|
||||
//@}
|
||||
|
||||
public:
|
||||
/** @name Building operations */
|
||||
//@{
|
||||
|
@ -51,7 +63,7 @@ public:
|
|||
/// Searches for a Building and creates it if it does not exist
|
||||
static const Building& find_create_building(const std::string &name) ;
|
||||
/// Searches the Area in which \em point is
|
||||
static const Area* in_which_area_is(const Point3D point) ;
|
||||
static const Area* in_which_area_is(const Point3D &point) ;
|
||||
//@}
|
||||
|
||||
/** @name Waypoint operations */
|
||||
|
|
|
@ -144,7 +144,7 @@ bool Timestamp::greater_than(const struct timespec &source) const
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Timestamp& Timestamp::operator=(const Timestamp &source)
|
||||
Timestamp& Timestamp::operator=(const Timestamp &source)
|
||||
{
|
||||
if (this == &source)
|
||||
return *this ;
|
||||
|
|
|
@ -62,9 +62,9 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Timestamp& operator=(const Timestamp &source) ;
|
||||
const Timestamp& operator=(const struct timespec &source) ;
|
||||
const Timestamp& operator=(const uint64_t source) ; //< deprecated
|
||||
Timestamp& operator=(const Timestamp &source) ;
|
||||
Timestamp& operator=(const struct timespec &source) ;
|
||||
Timestamp& operator=(const uint64_t source) ; //< deprecated
|
||||
bool operator==(const Timestamp &source) const ;
|
||||
bool operator==(const struct timespec &source) const ;
|
||||
bool operator==(const uint64_t source) const ; //< deprecated
|
||||
|
@ -109,15 +109,14 @@ inline void Timestamp::clear(void)
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
inline const Timestamp& Timestamp::
|
||||
operator=(const struct timespec &source)
|
||||
inline Timestamp& Timestamp::operator=(const struct timespec &source)
|
||||
{
|
||||
set(source) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
|
||||
inline const Timestamp& Timestamp::operator=(const uint64_t source)
|
||||
inline Timestamp& Timestamp::operator=(const uint64_t source)
|
||||
{
|
||||
set(source) ;
|
||||
return *this ;
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace po = boost::program_options ;
|
|||
/* *** Default value definitions *** */
|
||||
|
||||
#define DEFAULT_CONFIG_FILE_NAME \
|
||||
"/usr/local/etc/owlps/owlps-positioning.cfg"
|
||||
"/usr/local/etc/owlps/owlps-positioning.conf"
|
||||
|
||||
#define DEFAULT_TCPEVAAL_HOST "127.0.0.1"
|
||||
#define DEFAULT_TCPEVAAL_PORT 4444
|
||||
|
@ -183,12 +183,15 @@ void UserInterface::fill_positioning_options()
|
|||
"Algorithms used to compute positions. You can specify"
|
||||
"this option more than once (but at least once). Allowed: Real, FBCM,"
|
||||
" FRBHMBasic, InterlinkNetworks, RADAR.")
|
||||
("positioning.minmax-start", po::value<string>(),
|
||||
"Coordinates of the start point of the MinMax multilateration"
|
||||
" method (string format: \"X;Y;Z\").")
|
||||
("positioning.minmax-stop", po::value<string>(),
|
||||
"Coordinates of the stop point of the MinMax multilateration"
|
||||
" method (string format: \"X;Y;Z\").")
|
||||
("positioning.area-start", po::value<string>(),
|
||||
"Coordinates of the first point of the deployment area; this is"
|
||||
" used to delimit the area in which the MinMax multilateration"
|
||||
" method tests points and in which the reference points are"
|
||||
" generated, if the corresponding options are activated"
|
||||
" (string format: \"X;Y;Z\").")
|
||||
("positioning.area-stop", po::value<string>(),
|
||||
"Coordinates of the last point of the deployment area"
|
||||
" (string format: \"X;Y;Z\").")
|
||||
("positioning.radar-average-reference-points",
|
||||
po::value<bool>()->default_value(false),
|
||||
"With the RADAR algorithm, for a given positioning request, average"
|
||||
|
|
|
@ -53,7 +53,7 @@ Waypoint::~Waypoint()
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const Waypoint& Waypoint::operator=(const Waypoint &wp)
|
||||
Waypoint& Waypoint::operator=(const Waypoint &wp)
|
||||
{
|
||||
if (this == &wp)
|
||||
return *this ;
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const Waypoint& operator=(const Waypoint &wp) ;
|
||||
Waypoint& operator=(const Waypoint &wp) ;
|
||||
bool operator==(const Waypoint &wp) const ;
|
||||
bool operator!=(const Waypoint &wp) const ;
|
||||
operator std::string(void) const ;
|
||||
|
|
|
@ -7,7 +7,7 @@ using namespace std ;
|
|||
/* *** Operators *** */
|
||||
|
||||
|
||||
const WifiDevice& WifiDevice::operator=(const WifiDevice &wd)
|
||||
WifiDevice& WifiDevice::operator=(const WifiDevice &wd)
|
||||
{
|
||||
if (this == &wd)
|
||||
return *this ;
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
/** @name Operators */
|
||||
//@{
|
||||
const WifiDevice& operator=(const WifiDevice &wd) ;
|
||||
WifiDevice& operator=(const WifiDevice &wd) ;
|
||||
bool operator==(const WifiDevice &wd) const ;
|
||||
bool operator!=(const WifiDevice &wl) const ;
|
||||
//@}
|
||||
|
|
Loading…
Reference in New Issue