2011-08-18 23:10:49 +02:00
|
|
|
#include "owlps-resultreader-udp.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2011-08-19 17:10:05 +02:00
|
|
|
#include <assert.h>
|
|
|
|
|
2011-08-18 23:10:49 +02:00
|
|
|
|
|
|
|
#define CSV_DELIMITER ";"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Receives a result from the socket of file descriptor 'sockfd' and
|
|
|
|
* fills an owl_result structure 'result'.
|
|
|
|
*
|
|
|
|
* Note that *result will be set by this function, and **result will
|
|
|
|
* point on a valid owl_result structure if everything goes well.
|
|
|
|
* You will have to free *result yourself with owl_free_result().
|
|
|
|
*
|
|
|
|
* In case of error, *result is set to NULL.
|
|
|
|
*/
|
|
|
|
void owl_receive_position(int sockfd, owl_result **result)
|
|
|
|
{
|
|
|
|
ssize_t nread ; // recvfrom return value
|
|
|
|
char csv[OWL_CSV_RESULT_STRLEN] ; // Read string
|
|
|
|
|
|
|
|
nread = recvfrom(sockfd, &csv, OWL_CSV_RESULT_STRLEN,
|
|
|
|
0, NULL, NULL) ;
|
|
|
|
|
|
|
|
if (nread <= 0)
|
|
|
|
{
|
|
|
|
perror("No request received from listener") ;
|
|
|
|
*result = NULL ;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
owl_fill_result(result, csv) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Splits the 'csv' string received from OwlPS Positioning and stores
|
|
|
|
* the fields in 'result' (which is allocated).
|
|
|
|
*
|
|
|
|
* Handled CSV format:
|
|
|
|
* Mobile_MAC;Request_type;Request_timestamp;Algorithm;X;Y;Z;Error;Area
|
|
|
|
* The Request_timestamp format is:
|
|
|
|
* seconds.nanoseconds
|
|
|
|
*/
|
|
|
|
void owl_fill_result(owl_result **result, char *csv)
|
|
|
|
{
|
|
|
|
char *csv_field = NULL ;
|
|
|
|
int nb_algorithms = 0 ;
|
|
|
|
owl_algorithm_result *current_algo = NULL ;
|
|
|
|
|
|
|
|
*result = malloc(sizeof(owl_result)) ;
|
|
|
|
(*result)->results = NULL ;
|
|
|
|
|
|
|
|
/* Mobile MAC address */
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the mobile's MAC address from the CSV"
|
|
|
|
" string (empty string?)!\n") ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
(*result)->mobile_mac_addr =
|
|
|
|
strndup(csv_field, OWL_ETHER_ADDR_STRLEN) ;
|
|
|
|
|
|
|
|
/* Request type */
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the request type from the CSV string!\n") ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
(*result)->request_type = atoi(csv_field) ;
|
|
|
|
|
|
|
|
/* Timestamp */
|
|
|
|
// Seconds
|
|
|
|
csv_field = strsep(&csv, ".") ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the timestamp (seconds) from the CSV"
|
|
|
|
" string!\n") ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
(*result)->mobile_timestamp.tv_sec = atol(csv_field) ;
|
|
|
|
// Nanoseconds
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the timestamp (nanoseconds) from the CSV"
|
|
|
|
" string!\n") ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
(*result)->mobile_timestamp.tv_nsec = atol(csv_field) ;
|
|
|
|
|
|
|
|
/* Algorithm results */
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
++nb_algorithms ;
|
|
|
|
current_algo = malloc(sizeof(owl_algorithm_result)) ;
|
|
|
|
|
|
|
|
// Algorithm name
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the algorithm name from the CSV"
|
|
|
|
" string (algorithm #%d)!\n", nb_algorithms) ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
current_algo->algorithm =
|
|
|
|
strndup(csv_field, OWL_ALGORITHM_STRLEN) ;
|
|
|
|
|
|
|
|
// X coordinate
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the X coordinate from the CSV"
|
|
|
|
" string (algorithm #%d)!\n", nb_algorithms) ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
current_algo->x = atof(csv_field) ;
|
|
|
|
|
|
|
|
// Y coordinate
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the Y coordinate from the CSV"
|
|
|
|
" string (algorithm #%d)!\n", nb_algorithms) ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
current_algo->y = atof(csv_field) ;
|
|
|
|
|
|
|
|
// Z coordinate
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the Z coordinate from the CSV"
|
|
|
|
" string (algorithm #%d)!\n", nb_algorithms) ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
current_algo->z = atof(csv_field) ;
|
|
|
|
|
|
|
|
// Distance error
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (! csv_field)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"Error reading the distance error from the CSV"
|
|
|
|
" string (algorithm #%d)!\n", nb_algorithms) ;
|
|
|
|
goto error ;
|
|
|
|
}
|
|
|
|
current_algo->error = atof(csv_field) ;
|
|
|
|
|
|
|
|
// Area name (optional)
|
|
|
|
csv_field = strsep(&csv, CSV_DELIMITER) ;
|
|
|
|
if (csv_field)
|
|
|
|
current_algo->area = strndup(csv_field, OWL_AREA_STRLEN) ;
|
|
|
|
|
|
|
|
// Insert the current algorithm at the begining of the list
|
|
|
|
current_algo->next = (*result)->results ;
|
|
|
|
(*result)->results = current_algo ;
|
|
|
|
}
|
|
|
|
while ((csv_field = strsep(&csv, CSV_DELIMITER))) ;
|
|
|
|
|
|
|
|
return ; // Success
|
|
|
|
|
|
|
|
error:
|
|
|
|
owl_free_result(*result) ;
|
|
|
|
*result = NULL ;
|
|
|
|
free(current_algo) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prints an owl_result to the given stream.
|
|
|
|
*/
|
2011-08-19 17:10:05 +02:00
|
|
|
void owl_fprint_result(FILE *stream, const owl_result *const src)
|
2011-08-18 23:10:49 +02:00
|
|
|
{
|
|
|
|
char timestamp_str[OWL_TIMESTAMP_STRLEN] ;
|
|
|
|
|
2011-08-19 17:10:05 +02:00
|
|
|
assert(src) ;
|
|
|
|
|
|
|
|
owl_timestamp_to_string(timestamp_str, src->mobile_timestamp) ;
|
2011-08-18 23:10:49 +02:00
|
|
|
fprintf(stream,
|
|
|
|
"Mobile MAC: %s\n"
|
|
|
|
"Request type: %"PRIu8"\n"
|
|
|
|
"Mobile timestamp: %s\n"
|
|
|
|
"Results:\n"
|
|
|
|
,
|
2011-08-19 17:10:05 +02:00
|
|
|
src->mobile_mac_addr,
|
|
|
|
src->request_type,
|
2011-08-18 23:10:49 +02:00
|
|
|
timestamp_str
|
|
|
|
) ;
|
|
|
|
|
2011-08-19 17:10:05 +02:00
|
|
|
owl_algorithm_result *algo = src->results ;
|
2011-08-18 23:10:49 +02:00
|
|
|
while (algo)
|
|
|
|
{
|
|
|
|
owl_fprint_algorithm_result(stream, algo) ;
|
|
|
|
algo = algo->next ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2011-08-19 17:10:05 +02:00
|
|
|
* Prints an owl_algorithm_result to the given stream.
|
2011-08-18 23:10:49 +02:00
|
|
|
*/
|
|
|
|
void owl_fprint_algorithm_result(FILE *stream,
|
2011-08-19 17:10:05 +02:00
|
|
|
const owl_algorithm_result *const src)
|
2011-08-18 23:10:49 +02:00
|
|
|
{
|
2011-08-19 17:10:05 +02:00
|
|
|
assert(src) ;
|
|
|
|
|
2011-08-18 23:10:49 +02:00
|
|
|
fprintf(stream,
|
|
|
|
"* Algorithm: %s\n"
|
|
|
|
" X: %f\n"
|
|
|
|
" Y: %f\n"
|
|
|
|
" Z: %f\n"
|
|
|
|
" Error: %f\n"
|
|
|
|
" Area: %s\n"
|
|
|
|
,
|
2011-08-19 17:10:05 +02:00
|
|
|
src->algorithm,
|
|
|
|
src->x,
|
|
|
|
src->y,
|
|
|
|
src->z,
|
|
|
|
src->error,
|
|
|
|
src->area ? src->area : ""
|
2011-08-18 23:10:49 +02:00
|
|
|
) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Frees the memory allocated by an owl_result.
|
|
|
|
* Note that the pointer will not set to NULL.
|
|
|
|
*/
|
|
|
|
void owl_free_result(owl_result *result)
|
|
|
|
{
|
|
|
|
if (! result)
|
|
|
|
return ;
|
|
|
|
while (result->results)
|
|
|
|
{
|
|
|
|
owl_algorithm_result *algo = result->results ;
|
|
|
|
result->results = algo->next ;
|
|
|
|
owl_free_algorithm_result(algo) ;
|
|
|
|
}
|
|
|
|
free(result->mobile_mac_addr) ;
|
|
|
|
free(result) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Frees the memory allocated by a single owl_algorithm_result (*not*
|
|
|
|
* recursively).
|
|
|
|
* Note that the pointer will not set to NULL.
|
|
|
|
*/
|
|
|
|
void owl_free_algorithm_result(owl_algorithm_result *algo)
|
|
|
|
{
|
|
|
|
if (! algo)
|
|
|
|
return ;
|
|
|
|
free(algo->algorithm) ;
|
|
|
|
free(algo->area) ;
|
|
|
|
free(algo) ;
|
|
|
|
}
|