/* * 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 #else // __cplusplus # include #endif // __cplusplus #ifdef __cplusplus extern "C" { #endif // __cplusplus #include #include #include #include #include #include /** @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_