Owl Positioning System: a Wi-Fi-based, infrastructure-centred indoor positioning system. http://owlps.pu-pm.univ-fcomte.fr/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

465 lines
15 KiB

/*
* This file is part of the Owl Positioning System (OwlPS) project.
* It is subject to the copyright notice and license terms in the
* COPYRIGHT.t2t file found in the top-level directory of this
* distribution and at
* https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t
* No part of the OwlPS Project, including this file, may be copied,
* modified, propagated, or distributed except according to the terms
* contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
* distributed along with this file, either separately or by replacing
* this notice by the COPYRIGHT.t2t file's contents.
*/
/**
* @file owlps.h
* @brief OwlPS library
*
* libowlps is the library containing the code shared by most of the
* OwlPS programs.
*/
#ifndef _LIBOWLPS_H_
#define _LIBOWLPS_H_
#ifdef __cplusplus
# include <cstdint>
#else // __cplusplus
# include <stdint.h>
#endif // __cplusplus
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
/** @name Network ports */
//@{
/// Port on which the positioning and calibration requests are sent by
/// the mobiles (or the listeners for autocalibration requests)
#define OWL_DEFAULT_REQUEST_PORT 9900
/// Port on which listeners and aggregator communicate
#define OWL_DEFAULT_LISTENER_PORT 9901
/// Port on which Aggregator and Positioner communicate
#define OWL_DEFAULT_AGGREGATION_PORT 9902
/// Port on which the aggregator listens for hello messages from the
/// listeners
#define OWL_DEFAULT_AUTOCALIBRATION_HELLO_PORT 9903
/// Port on which the listeners listen for orders from the aggregator
#define OWL_DEFAULT_AUTOCALIBRATION_ORDER_PORT 9904
/// Port on which the mobile listens for its position
#define OWL_DEFAULT_RESULT_PORT 9910
//@}
/** @name Miscellaneous informations */
//@{
#define OWL_LATEST_AGGREGATION_CSV_FORMAT 1
//@}
/// Directions
enum owl_directions
{
owl_north = 1, ///< North direction
owl_east, ///< East direction
owl_south, ///< South direction
owl_west ///< West direction
} ;
/// First [direction](@ref owl_direction)
#define OWL_DIRECTION_MIN 1
/// Last [direction](@ref owl_direction)
#define OWL_DIRECTION_MAX 4
/// Direction type
typedef uint8_t owl_direction ;
/// Timestamp structure
/**
* This timestamp structure is a clone of `struct timespec` (from
* `time.h`), but with fixed-size fields.
*/
struct _owl_timestamp
{
uint32_t tv_sec ; ///< Seconds
uint32_t tv_nsec ; ///< Nanoseconds
} ;
/// Timestamp type
typedef struct _owl_timestamp owl_timestamp ;
/** @name String lengths */
//@{
/// Length of a owl_timestamp when converted to string
/**
* 22 = 10 digits, '.', 10 digits, '\0'
*/
#define OWL_TIMESTAMP_STRLEN 22
//@}
/// Message sent by the Listener to the Aggregator
/**
* Message sent by the Listener to the Aggregator for each captured
* request.
*
* TODO: This structure's size could be reduced from 60 to 52 byte by reordering
* the fields by size.
*/
struct _owl_captured_request
{
uint8_t type ; ///< Type of the captured request
unsigned char __pad0; // 1 byte alignment
uint16_t nb_packets ; ///< Number of packets for this request
uint16_t packet_id ; ///< Number of the current packet
uint8_t cp_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the listener
uint8_t mobile_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the mobile
uint8_t mobile_ip_addr_bytes[4] ; ///< IP of the mobile
unsigned char __pad1[2]; // 2 bytes alignment
owl_timestamp request_time ; ///< Timestamp on the mobile
owl_timestamp capture_time ; ///< Timestamp of arrival on the listener
int8_t ss_dbm ; ///< Signal strength measured by the listener (dBm)
unsigned char __pad2[3]; // 3 bytes alignment
/* Calibration data */
float x_position ; ///< X coordinate
float y_position ; ///< Y coordinate
float z_position ; ///< Z coordinate
owl_direction direction ; ///< Orientation of the mobile
unsigned char __pad3[3]; // 3 bytes alignment
} ;
/// Captured request type
typedef struct _owl_captured_request owl_captured_request ;
/// Message sent by the Aggregator to the Positioner (request's data)
/**
* Message sent by the Aggregator to the Positioner containing
* the main data of a request.
*
* TODO: This structure's size could be reduced from 44 to 36 bytes by
* reordering the fields by size.
*/
struct _owl_request
{
uint8_t type ; ///< Type of the request
unsigned char __pad0; // 1 byte alignment
uint16_t nb_packets ; ///< Number of packets sent for this request
uint8_t mobile_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the mobile
uint8_t mobile_ip_addr_bytes[4] ; ///< IP of the mobile
unsigned char __pad1[2]; // 2 bytes alignment
owl_timestamp request_time ; ///< Timestamp on the mobile
uint16_t nb_info ; ///< Number of owl_request_info
unsigned char __pad2[2]; // 2 bytes alignment
/* Calibration data */
float x_position ; ///< X coordinate
float y_position ; ///< Y coordinate
float z_position ; ///< Z coordinate
owl_direction direction ; ///< Orientation of the mobile
unsigned char __pad3[3]; // 3 bytes alignment
} ;
/// Aggregated request type
typedef struct _owl_request owl_request ;
/// Message sent by the Aggregator to the Positioner (signal strength)
/**
* Message sent by the Aggregator to the Positioner refering to
* a request, indicating that a CP received the request with a given
* signal strength.
*/
struct _owl_request_info
{
uint16_t packet_id ; ///< Number of the current packet
uint8_t cp_mac_addr_bytes[ETHER_ADDR_LEN] ; ///< MAC of the listener
owl_timestamp capture_time ; ///< Timestamp of arrival on the listener
int8_t ss_dbm ; ///< Signal strength measured by the listener (dBm)
unsigned char __pad0[3]; // 3 bytes alignment
} ;
/// Aggregated request information type
typedef struct _owl_request_info owl_request_info ;
/// *Hello* message sent by the Listener to the Aggregator
/**
* This structure represents a *hello* message sent to the Aggregator by
* each Listener to signal its presence.
*/
struct _owl_autocalibration_hello
{
/// MAC address of the Listener
uint8_t cp_mac_addr_bytes[ETHER_ADDR_LEN] ;
} ;
/// *Hello* message type
typedef struct _owl_autocalibration_hello owl_autocalibration_hello ;
/// Message sent to the Listener to order an emission
/**
* This structure represents a message sent by the Aggregator to a
* Listener to order it to send an autocalibration request.
*/
struct _owl_autocalibration_order
{
uint8_t order ; ///< Code of the order
} ;
/// Autocalibration order type
typedef struct _owl_autocalibration_order owl_autocalibration_order ;
/** @name Autocalibration order type identifiers */
//@{
#define AUTOCALIBRATION_ORDER_SEND 1
//@}
/** @name Request type identifiers */
//@{
/// "Normal" positioning request
#define OWL_REQUEST_NORMAL 0
/// Calibration request
#define OWL_REQUEST_CALIBRATION 1
/// Autocalibration request
#define OWL_REQUEST_AUTOCALIBRATION 2
/// Generated request (in Positioner)
#define OWL_REQUEST_GENERATED 3
/// Implicit positioning request
#define OWL_REQUEST_IMPLICIT 10
/// Undefined or unknown request type
#define OWL_REQUEST_UNDEFINED 255
//@}
/* Don't forget to update the OWL_IS_REQUEST_TYPE macro below when you
* change something here! */
/** @name Wi-Fi channels' frequencies in MHz */
//@{
#define OWL_80211_MHZ_CHANNEL_1 2412
#define OWL_80211_MHZ_CHANNEL_2 2417
#define OWL_80211_MHZ_CHANNEL_3 2422
#define OWL_80211_MHZ_CHANNEL_4 2427
#define OWL_80211_MHZ_CHANNEL_5 2432
#define OWL_80211_MHZ_CHANNEL_6 2437
#define OWL_80211_MHZ_CHANNEL_7 2442
#define OWL_80211_MHZ_CHANNEL_8 2447
#define OWL_80211_MHZ_CHANNEL_9 2452
#define OWL_80211_MHZ_CHANNEL_10 2457
#define OWL_80211_MHZ_CHANNEL_11 2462
#define OWL_80211_MHZ_CHANNEL_12 2467
#define OWL_80211_MHZ_CHANNEL_13 2472
#define OWL_80211_MHZ_CHANNEL_14 2477
//@}
/** @name Wi-Fi channels' frequencies in Hz */
//@{
#define OWL_80211_HZ_CHANNEL_1 2412000000ul
#define OWL_80211_HZ_CHANNEL_2 2417000000ul
#define OWL_80211_HZ_CHANNEL_3 2422000000ul
#define OWL_80211_HZ_CHANNEL_4 2427000000ul
#define OWL_80211_HZ_CHANNEL_5 2432000000ul
#define OWL_80211_HZ_CHANNEL_6 2437000000ul
#define OWL_80211_HZ_CHANNEL_7 2442000000ul
#define OWL_80211_HZ_CHANNEL_8 2447000000ul
#define OWL_80211_HZ_CHANNEL_9 2452000000ul
#define OWL_80211_HZ_CHANNEL_10 2457000000ul
#define OWL_80211_HZ_CHANNEL_11 2462000000ul
#define OWL_80211_HZ_CHANNEL_12 2467000000ul
#define OWL_80211_HZ_CHANNEL_13 2472000000ul
#define OWL_80211_HZ_CHANNEL_14 2477000000ul
//@}
/** @name String lengths */
//@{
/// Length of a MAC address in string format (including '\0')
#define OWL_ETHER_ADDR_STRLEN 18
/// Maximum length of an algorithm name (including '\0')
#define OWL_ALGORITHM_STRLEN 31
/// Maximum length of an area name (including '\0')
#define OWL_AREA_STRLEN 31
/// Maximum length of a coordinate X, Y or Z (including '\0')
#define OWL_COORDINATE_STRLEN 16
//@}
/* Global variables */
/// Global variable used to handle end of loops
extern bool owl_run ;
/** @name Error codes */
//@{
/// Wrong program invokation (command-line arguments)
#define OWL_ERR_BAD_USAGE 100
/// Error when reading/parsing the configuration file
#define OWL_ERR_CONFIG_FILE 101
/* System */
/// Error when creating a thread
#define OWL_ERR_THREAD_CREATE 110
/// Wrong signal received
#define OWL_ERR_BAD_SIGNAL 111
/* Network communication */
/// Error when creating a socket
#define OWL_ERR_SOCKET_CREATE 120
/// Error when sending a message on a socket
#define OWL_ERR_SOCKET_SEND 121
/// Error when reading from a socket
#define OWL_ERR_SOCKET_RECV 122
/* Network interface / capture */
/// Error when opening the capture interface
#define OWL_ERR_IFACE_PCAP_OPEN 130
/// Error when reading the interface Wi-Fi mode
#define OWL_ERR_IFACE_MODE_GET 131
/// Error when setting the interface Wi-Fi mode
#define OWL_ERR_IFACE_MODE_SET 132
//@}
/* Macros */
/// Converts a bool to the corresponding string
#define OWL_BOOL_TO_STRING(B) ((B) ? "true" : "false")
/// Make sure the given integer is a valid request type
/**
* True if `I` is a valid request type, false otherwise.
* Do *not* pass an incremented number to this macro (e.g. type++ or
* ++type). This shouldn't be a problem with a request type, though.
*/
#define OWL_IS_REQUEST_TYPE(I) \
( (I) == OWL_REQUEST_NORMAL \
|| (I) == OWL_REQUEST_CALIBRATION \
|| (I) == OWL_REQUEST_AUTOCALIBRATION \
|| (I) == OWL_REQUEST_GENERATED \
|| (I) == OWL_REQUEST_IMPLICIT \
|| (I) == OWL_REQUEST_UNDEFINED)
/* Function headers */
/** @name Miscellaneous */
//@{
/// Converts a MAC address from bytes to string
const char* owl_mac_bytes_to_string(const uint8_t *const mac_binary) ;
/// Converts a MAC address from bytes to string
void owl_mac_bytes_to_string_r(const uint8_t *const mac_binary,
char mac_str[OWL_ETHER_ADDR_STRLEN]) ;
/// Compares two MAC addresses
bool owl_mac_equals(const uint8_t *const mac1,
const uint8_t *const mac2) ;
/// Converts a IEEE 802.11 frequency into a channel number
uint_fast8_t owl_frequency_to_channel(const uint_fast16_t frequency) ;
//@}
/** @name Time */
//@{
/// Sleeps for a given amount of milliseconds
int owl_msleep(uint32_t time_ms) ;
/// Sets the `owl_timestamp` `now` to the current time
int owl_timestamp_now(owl_timestamp *const now) ;
/// Converts a `struct timespec` to an `owl_timestamp`
void owl_timespec_to_timestamp(const struct timespec *const src,
owl_timestamp *const dst) ;
/// Converts a `struct timeval` to an `owl_timestamp`
void owl_timeval_to_timestamp(const struct timeval *const src,
owl_timestamp *const dst) ;
/// Compares two `owl_timestamp`
bool owl_timestamp_equals(const owl_timestamp *const d1,
const owl_timestamp *const d2) ;
/// Converts an `owl_timestamp` date value into milliseconds
uint64_t owl_timestamp_to_ms(const owl_timestamp *const d) ;
/// Converts an `owl_timestamp` date value into a printable string
void owl_timestamp_to_string(const owl_timestamp *const src,
char *const dst) ;
/// Returns the time (in milliseconds) between two dates
uint_fast32_t owl_time_elapsed_ms(const owl_timestamp *const d1,
const owl_timestamp *const d2) ;
/// Computes the time difference between two dates
void owl_time_elapsed(const owl_timestamp *const d1,
const owl_timestamp *const d2,
owl_timestamp *const elapsed) ;
//@}
/** @name Endianness */
//@{
/// Changes the endianness of an `owl_timestamp` from host to network
/// order
void owl_hton_timestamp(owl_timestamp *const d) ;
/// Changes the endianness of an `owl_timestamp` from network to host
/// order
void owl_ntoh_timestamp(owl_timestamp *const d) ;
/// Changes the order of the bytes of a `float`
float owl_swap_float(const float f) ;
//@}
/** @name Endianness-related macros */
//@{
/**
* @def owl_htonf
* @brief Changes the endianness of a `float` from host to network
*
* This macro converts the byte order of a `float` if needed, depending
* on the endianness of the host, to adopt the endianness of the network.
* To actually change the byte order, the owl_swap_float() function is
* used.
*
* @def owl_ntohf
* @brief Changes the endianness of a `float` from network to host
*
* This macro converts the byte order of a `float` encoded with a network
* endianness to adopt the endianness of the host, if the two endianness
* are different.
* To actually change the byte order, the owl_swap_float() function is
* used.
*/
//@}
#if __BYTE_ORDER == __BIG_ENDIAN
# define owl_htonf(f) (f)
# define owl_ntohf(f) (f)
#else // __BYTE_ORDER == __BIG_ENDIAN
# if __BYTE_ORDER == __LITTLE_ENDIAN
# define owl_htonf(f) owl_swap_float(f)
# define owl_ntohf(f) owl_swap_float(f)
# else // __BYTE_ORDER == __LITTLE_ENDIAN
# error "This program does not handle strange architectures."
# endif // __BYTE_ORDER == __LITTLE_ENDIAN
#endif // __BYTE_ORDER == __BIG_ENDIAN
/** @name Network */
//@{
/// Opens a UDP transmission socket
int owl_create_udp_trx_socket(const char *const server_address,
const uint_fast16_t server_port,
struct sockaddr *const server_description) ;
/// Opens a UDP reception socket
int owl_create_udp_listening_socket(const uint_fast16_t port) ;
//@}
/** @name Signals */
//@{
/// Generic signal handler for SIGINT
void owl_sigint_handler(const int num) ;
/// Generic signal handler for SIGTERM
void owl_sigterm_handler(const int num) ;
//@}
/** @name Threads */
//@{
/// Closes the file descriptor `fd`
void owl_close_fd(void *const fd) ;
/// Closes the stream `file`
void owl_close_file(void *const file) ;
//@}
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _LIBOWLPS_H_