From 191109c5b0131a20c7210f4eb4d0810f627695ef Mon Sep 17 00:00:00 2001 From: Julien Graeffly Date: Fri, 29 May 2009 12:07:05 +0000 Subject: [PATCH] =?UTF-8?q?Reconstitution=20du=20d=C3=A9p=C3=B4t,=20=C3=A9?= =?UTF-8?q?tape=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le commentaire de révision initial figure ci-dessous. Les différences par rapport à ce commit sont les suivantes : - client/ : la version binaire n'est pas versionnée, ni "toutes.csv". - Non-suppression de clientinfo.* et de guinumo.* (on verra plus tard). - Les fichiers de conf restent dans le répertoire "cfg", qui n'est pas supprimé. - Le répertoire "csv" reste vide (les données d'entrée n'ont pas à être versionnées). - Le répertoire "log" n'est pas supprimé. | r89 | jgraeffly | 2009-05-15 14:54:13 +0200 (ven 15 mai 2009) | 11 lines | Chemins modifiés : | R /code/owlps-positioning/Makefile | D /code/owlps-positioning/TODO | D /code/owlps-positioning/cfg | A /code/owlps-positioning/client | A /code/owlps-positioning/client/Client | A /code/owlps-positioning/client/Client.cc | A /code/owlps-positioning/client/toutes.csv | D /code/owlps-positioning/clientinfo.cc | D /code/owlps-positioning/clientinfo.hh | R /code/owlps-positioning/csv | A /code/owlps-positioning/csv/minipc.cfg | A /code/owlps-positioning/csv/topo.csv | A /code/owlps-positioning/csv/toutes.csv | A /code/owlps-positioning/csv/waypoints.csv | D /code/owlps-positioning/guinumo.cc | D /code/owlps-positioning/guinumo.hh | D /code/owlps-positioning/log | A /code/owlps-positioning/positioning.cc | A /code/owlps-positioning/positioning.hh | R /code/owlps-positioning/server.cc | R /code/owlps-positioning/server.hh | A /code/owlps-positioning/treatment.cc | A /code/owlps-positioning/treatment.hh | | - Création du serveur qui reçois les informations à partir du client | se trouvant dans le dossier client/ | - Implémentation de la partie calcul dans le serveur (les résultats | sont cependant les mêmes qu'avant il n'y a pour l'instant pas eu de | modifications sur le traitement). | - En sortie, on retrouve le résultat de chaques algo. | - Sur cette version il n'y a pas encore de commentaires ceci a été | fait afin d'avoir une meilleure visualisation du programme. | - La réception des données se fait pour l'instant toujours grâce à un | vector | - positioning.cc est une classe qui contient les informations sur la | topologie les AP ainsi que les points de référence. | - server.cc contient les méthodes qui permet de recevoir les clients | et implémente positioning.cc avec les informations reçues par des | fichiers ces fichiers sont dans csv/ | - treatment.cc est une classe contenant les différents Algo permettant | de calculer la position. | - Pour éxécuter le programme : owlps-positioningd csv/minipc.cfg | csv/toutes.csv csv/topo.csv csv/waypoints.csv git-svn-id: https://pif.pu-pm.univ-fcomte.fr/svn/loc@90 785a6c6c-259e-4ff1-8b91-dc31627914f0 --- owlps-positioning/Makefile | 17 +- owlps-positioning/TODO | 4 - owlps-positioning/client/Client.cc | 443 +++++ owlps-positioning/positioning.cc | 651 +++++++ owlps-positioning/positioning.hh | 84 + owlps-positioning/server.cc | 2707 ++-------------------------- owlps-positioning/server.hh | 168 +- owlps-positioning/treatment.cc | 382 ++++ owlps-positioning/treatment.hh | 57 + 9 files changed, 1773 insertions(+), 2740 deletions(-) delete mode 100644 owlps-positioning/TODO create mode 100644 owlps-positioning/client/Client.cc create mode 100644 owlps-positioning/positioning.cc create mode 100644 owlps-positioning/positioning.hh create mode 100644 owlps-positioning/treatment.cc create mode 100644 owlps-positioning/treatment.hh diff --git a/owlps-positioning/Makefile b/owlps-positioning/Makefile index 03eb9e7..75da0ac 100644 --- a/owlps-positioning/Makefile +++ b/owlps-positioning/Makefile @@ -4,32 +4,35 @@ GXXFLAGS = $(DEBUG) -Wall -pedantic LD = g++ LDFLAGS = -lm -TARGET = guinumo -HEADER = guinumo.hh +TARGET = owlps-positioningd +HEADER = owlps-positioning.hh all : ${TARGET} + @rm -f *~ *.o + % : %.o $(LD) $(LDFLAGS) -o $@ $^ %.o : %.cc $(HEADER) $(GXX) $(GXXFLAGS) -c $< -clientinfo.o : clientinfo.hh point.hh -server.o : server.hh clientinfo.hh referencepoint.hh accesspoint.hh point.hh measurement.hh area.hh +positioning.o : point.hh referencepoint.hh accesspoint.hh area.hh +server.o : server.hh positioning.hh point.hh measurement.hh treatment.hh referencepoint.o : referencepoint.hh measurement.hh point.hh accesspoint.o : accesspoint.hh point.hh point.o : point.hh measurement.o : measurement.hh area.o : area.hh point.hh -guinumo.o : point.hh measurement.hh accesspoint.hh referencepoint.hh clientinfo.hh server.hh +treatment.o : treatment.hh point.hh measurement.hh referencepoint.hh accesspoint.hh +owlps-positioning.o : server.hh -${TARGET} : point.o measurement.o accesspoint.o referencepoint.o clientinfo.o server.o area.o +${TARGET} : point.o measurement.o accesspoint.o referencepoint.o positioning.o server.o area.o treatment.o clean: @rm -fv *~ *.o purge : clean - @rm -fv guinumo + @rm -fv owlps-positioningd install : @echo "La cible d'installation de ${TARGET} sera implémentée prochainement. Vous devez lancer le programme 'guinumo' depuis le répertoire des sources." diff --git a/owlps-positioning/TODO b/owlps-positioning/TODO deleted file mode 100644 index e7c2d08..0000000 --- a/owlps-positioning/TODO +++ /dev/null @@ -1,4 +0,0 @@ -* ClientInfo : classe qui doit contenir les données des utilisateurs. - - IP, - - Socket, - → plus tard, pour une vraie démo. diff --git a/owlps-positioning/client/Client.cc b/owlps-positioning/client/Client.cc new file mode 100644 index 0000000..693bdef --- /dev/null +++ b/owlps-positioning/client/Client.cc @@ -0,0 +1,443 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +using namespace std; + +typedef struct _couple_info{ + unsigned char ap_mac_addr_bytes[6]; // Adresse MAC de l'AP + int antenna_signal_dbm; // Puissance du signal reçu par l'AP +} couple_info; + +typedef struct _demande{ + unsigned char ag_mac_addr_bytes[6]; // Adresse MAC de l'Aggregateur émetteur de la demande + int nb_couples; // Nombre couples (MAC AP;Puissance) +} demande; + +char* mac_bytes_to_string(unsigned char *mac_binary) ; +int create_udp_sending_socket(char *server_address, int server_port, struct sockaddr_in *server_description, struct sockaddr_in * client_description) ; +void get_mac_addr(char *eth, unsigned char mac_bytes[6]); +int split(string buffer, vector &envoi_info); +unsigned char convertuchar(char *caractere, int); + +int main(int argc, char **argv){ + + int sockfd, n = 0; + struct sockaddr_in serv; + struct sockaddr_in client; + unsigned char mac[6]; + ifstream fichier(argv[3]); + string cppbuffer; + + vector envoi_info; + demande envoi_demande; + + + if (argc != 4){ + cerr << "usage: Client IPaddress interface fichier" << endl; + exit(1); + } + + sockfd = create_udp_sending_socket(argv[1], 1234, &serv, &client); + + if(sockfd < 0){ + cerr << "Erreur ! Impossible de créer la socket vers le serveur de localisation" << endl; + return 1; + } + get_mac_addr(argv[2], mac) ; + memcpy(envoi_demande.ag_mac_addr_bytes, mac, 6); + + if(fichier){ + getline(fichier, cppbuffer); + envoi_demande.nb_couples = split(cppbuffer, envoi_info); + } + + n = sendto(sockfd, (void *)&envoi_demande, sizeof(envoi_demande), 0, (struct sockaddr *)&serv, (socklen_t) sizeof(serv)) ; + + for(int i = 0; i < envoi_demande.nb_couples; i++) + sendto(sockfd, (void *)&envoi_info.at(i), sizeof(couple_info), 0, (struct sockaddr *)&serv, (socklen_t) sizeof(serv)); + + exit(0); +} + +void get_mac_addr(char *eth, unsigned char mac_bytes[6]) +{ + struct ifreq ifr; + int sockfd ; + + bzero(mac_bytes, sizeof(unsigned char) * 6) ; // RàZ + + sockfd = socket(AF_INET, SOCK_DGRAM, 0) ; + if(sockfd < 0) + perror("Impossible d'ouvrir la socket pour récupérer l'adresse MAC ") ; + + strncpy(ifr.ifr_name, eth, IFNAMSIZ) ; + + if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) + return ; + + if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) + return ; + + memcpy(mac_bytes, ifr.ifr_hwaddr.sa_data, 6) ; +} + +int split(string buffer, vector &envoi_info){ + + unsigned char mac[6]; + int valueI; + char c[4]; + couple_info elem; + int i = 0; + int nb = 0; + + while(i < buffer.size()){ + + for(int j = 0; j < 6; j++){ + c[0] = buffer[i++]; + c[1] = buffer[i++]; + c[2] = '\0'; + mac[j] = convertuchar(c, 0); + i++; + } + c[0] = buffer[i++]; + c[1] = buffer[i++]; + c[2] = buffer[i++]; + c[3] = '\0'; + i++; + valueI = atoi(c); + memcpy(elem.ap_mac_addr_bytes, mac, 6); + elem.antenna_signal_dbm = valueI; + envoi_info.resize(nb+1); + envoi_info.at(nb) = elem; + nb++; + } + + return nb; +} + +char* mac_bytes_to_string(unsigned char *mac_binary) +{ + char *ret = (char *)malloc(sizeof(char) * 18) ; + + sprintf(ret, "%02x:%02x:%02x:%02x:%02x:%02x", mac_binary[0], mac_binary[1], mac_binary[2], mac_binary[3], mac_binary[4], mac_binary[5]) ; + ret[17] = '\0' ; + + return ret ; +} + +int create_udp_sending_socket(char *server_address, int server_port, struct sockaddr_in *server_description, struct sockaddr_in * client_description){ + + int sockfd ; // Descripteur de la socket + + /* Ceation de la socket UDP */ + sockfd = socket(AF_INET, SOCK_DGRAM, 0) ; + if (sockfd < 0){ + cerr << "Échec de la création de la socket " << endl; + return sockfd; + } + + /* Remise à zéro et initialisation de la structure du client */ + bzero((char *) client_description, sizeof(*client_description)) ; + client_description->sin_family = AF_INET ; // Socket INET + client_description->sin_addr.s_addr = htonl(INADDR_ANY) ; // Toutes les connexions + + /* Remise à zéro et initialisation de la structure du serveur */ + bzero((char *) server_description, sizeof(*server_description)) ; // RÀZ + server_description->sin_family = AF_INET ; // Socket INET + server_description->sin_addr.s_addr = inet_addr(server_address) ; // Adresse du serveur + server_description->sin_port = htons(server_port) ; // Port d'écoute du serveur + + return sockfd ; // On retourne le descripteur de la socket créée +} + +unsigned char convertuchar(char *caractere, int debut) { + + int i = debut; + + if (caractere[i] == '0' && caractere[i + 1] == '0') return 0x00; + if (caractere[i] == '0' && caractere[i + 1] == '1') return 0x01; + if (caractere[i] == '0' && caractere[i + 1] == '2') return 0x02; + if (caractere[i] == '0' && caractere[i + 1] == '3') return 0x03; + if (caractere[i] == '0' && caractere[i + 1] == '4') return 0x04; + if (caractere[i] == '0' && caractere[i + 1] == '5') return 0x05; + if (caractere[i] == '0' && caractere[i + 1] == '6') return 0x06; + if (caractere[i] == '0' && caractere[i + 1] == '7') return 0x07; + if (caractere[i] == '0' && caractere[i + 1] == '8') return 0x08; + if (caractere[i] == '0' && caractere[i + 1] == '9') return 0x09; + if (caractere[i] == '0' && caractere[i + 1] == 'a') return 0x0a; + if (caractere[i] == '0' && caractere[i + 1] == 'b') return 0x0b; + if (caractere[i] == '0' && caractere[i + 1] == 'c') return 0x0c; + if (caractere[i] == '0' && caractere[i + 1] == 'd') return 0x0d; + if (caractere[i] == '0' && caractere[i + 1] == 'e') return 0x0e; + if (caractere[i] == '0' && caractere[i + 1] == 'f') return 0x0f; + + if (caractere[i] == '1' && caractere[i + 1] == '0') return 0x10; + if (caractere[i] == '1' && caractere[i + 1] == '1') return 0x11; + if (caractere[i] == '1' && caractere[i + 1] == '2') return 0x12; + if (caractere[i] == '1' && caractere[i + 1] == '3') return 0x13; + if (caractere[i] == '1' && caractere[i + 1] == '4') return 0x14; + if (caractere[i] == '1' && caractere[i + 1] == '5') return 0x15; + if (caractere[i] == '1' && caractere[i + 1] == '6') return 0x16; + if (caractere[i] == '1' && caractere[i + 1] == '7') return 0x17; + if (caractere[i] == '1' && caractere[i + 1] == '8') return 0x18; + if (caractere[i] == '1' && caractere[i + 1] == '9') return 0x19; + if (caractere[i] == '1' && caractere[i + 1] == 'a') return 0x1a; + if (caractere[i] == '1' && caractere[i + 1] == 'b') return 0x1b; + if (caractere[i] == '1' && caractere[i + 1] == 'c') return 0x1c; + if (caractere[i] == '1' && caractere[i + 1] == 'd') return 0x1d; + if (caractere[i] == '1' && caractere[i + 1] == 'e') return 0x1e; + if (caractere[i] == '1' && caractere[i + 1] == 'f') return 0x1f; + + if (caractere[i] == '2' && caractere[i + 1] == '0') return 0x20; + if (caractere[i] == '2' && caractere[i + 1] == '1') return 0x21; + if (caractere[i] == '2' && caractere[i + 1] == '2') return 0x22; + if (caractere[i] == '2' && caractere[i + 1] == '3') return 0x23; + if (caractere[i] == '2' && caractere[i + 1] == '4') return 0x24; + if (caractere[i] == '2' && caractere[i + 1] == '5') return 0x25; + if (caractere[i] == '2' && caractere[i + 1] == '6') return 0x26; + if (caractere[i] == '2' && caractere[i + 1] == '7') return 0x27; + if (caractere[i] == '2' && caractere[i + 1] == '8') return 0x28; + if (caractere[i] == '2' && caractere[i + 1] == '9') return 0x29; + if (caractere[i] == '2' && caractere[i + 1] == 'a') return 0x2a; + if (caractere[i] == '2' && caractere[i + 1] == 'b') return 0x2b; + if (caractere[i] == '2' && caractere[i + 1] == 'c') return 0x2c; + if (caractere[i] == '2' && caractere[i + 1] == 'd') return 0x2d; + if (caractere[i] == '2' && caractere[i + 1] == 'e') return 0x2e; + if (caractere[i] == '2' && caractere[i + 1] == 'f') return 0x2f; + + if (caractere[i] == '3' && caractere[i + 1] == '0') return 0x30; + if (caractere[i] == '3' && caractere[i + 1] == '1') return 0x31; + if (caractere[i] == '3' && caractere[i + 1] == '2') return 0x32; + if (caractere[i] == '3' && caractere[i + 1] == '3') return 0x33; + if (caractere[i] == '3' && caractere[i + 1] == '4') return 0x34; + if (caractere[i] == '3' && caractere[i + 1] == '5') return 0x35; + if (caractere[i] == '3' && caractere[i + 1] == '6') return 0x36; + if (caractere[i] == '3' && caractere[i + 1] == '7') return 0x37; + if (caractere[i] == '3' && caractere[i + 1] == '8') return 0x38; + if (caractere[i] == '3' && caractere[i + 1] == '9') return 0x39; + if (caractere[i] == '3' && caractere[i + 1] == 'a') return 0x3a; + if (caractere[i] == '3' && caractere[i + 1] == 'b') return 0x3b; + if (caractere[i] == '3' && caractere[i + 1] == 'c') return 0x3c; + if (caractere[i] == '3' && caractere[i + 1] == 'd') return 0x3d; + if (caractere[i] == '3' && caractere[i + 1] == 'e') return 0x3e; + if (caractere[i] == '3' && caractere[i + 1] == 'f') return 0x3f; + + if (caractere[i] == '4' && caractere[i + 1] == '0') return 0x40; + if (caractere[i] == '4' && caractere[i + 1] == '1') return 0x41; + if (caractere[i] == '4' && caractere[i + 1] == '2') return 0x42; + if (caractere[i] == '4' && caractere[i + 1] == '3') return 0x43; + if (caractere[i] == '4' && caractere[i + 1] == '4') return 0x44; + if (caractere[i] == '4' && caractere[i + 1] == '5') return 0x45; + if (caractere[i] == '4' && caractere[i + 1] == '6') return 0x46; + if (caractere[i] == '4' && caractere[i + 1] == '7') return 0x47; + if (caractere[i] == '4' && caractere[i + 1] == '8') return 0x48; + if (caractere[i] == '4' && caractere[i + 1] == '9') return 0x49; + if (caractere[i] == '4' && caractere[i + 1] == 'a') return 0x4a; + if (caractere[i] == '4' && caractere[i + 1] == 'b') return 0x4b; + if (caractere[i] == '4' && caractere[i + 1] == 'c') return 0x4c; + if (caractere[i] == '4' && caractere[i + 1] == 'd') return 0x4d; + if (caractere[i] == '4' && caractere[i + 1] == 'e') return 0x4e; + if (caractere[i] == '4' && caractere[i + 1] == 'f') return 0x4f; + + if (caractere[i] == '5' && caractere[i + 1] == '0') return 0x50; + if (caractere[i] == '5' && caractere[i + 1] == '1') return 0x51; + if (caractere[i] == '5' && caractere[i + 1] == '2') return 0x52; + if (caractere[i] == '5' && caractere[i + 1] == '3') return 0x53; + if (caractere[i] == '5' && caractere[i + 1] == '4') return 0x54; + if (caractere[i] == '5' && caractere[i + 1] == '5') return 0x55; + if (caractere[i] == '5' && caractere[i + 1] == '6') return 0x56; + if (caractere[i] == '5' && caractere[i + 1] == '7') return 0x57; + if (caractere[i] == '5' && caractere[i + 1] == '8') return 0x58; + if (caractere[i] == '5' && caractere[i + 1] == '9') return 0x59; + if (caractere[i] == '5' && caractere[i + 1] == 'a') return 0x5a; + if (caractere[i] == '5' && caractere[i + 1] == 'b') return 0x5b; + if (caractere[i] == '5' && caractere[i + 1] == 'c') return 0x5c; + if (caractere[i] == '5' && caractere[i + 1] == 'd') return 0x5d; + if (caractere[i] == '5' && caractere[i + 1] == 'e') return 0x5e; + if (caractere[i] == '5' && caractere[i + 1] == 'f') return 0x5f; + + if (caractere[i] == '6' && caractere[i + 1] == '0') return 0x60; + if (caractere[i] == '6' && caractere[i + 1] == '1') return 0x61; + if (caractere[i] == '6' && caractere[i + 1] == '2') return 0x62; + if (caractere[i] == '6' && caractere[i + 1] == '3') return 0x63; + if (caractere[i] == '6' && caractere[i + 1] == '4') return 0x64; + if (caractere[i] == '6' && caractere[i + 1] == '5') return 0x65; + if (caractere[i] == '6' && caractere[i + 1] == '6') return 0x66; + if (caractere[i] == '6' && caractere[i + 1] == '7') return 0x67; + if (caractere[i] == '6' && caractere[i + 1] == '8') return 0x68; + if (caractere[i] == '6' && caractere[i + 1] == '9') return 0x69; + if (caractere[i] == '6' && caractere[i + 1] == 'a') return 0x6a; + if (caractere[i] == '6' && caractere[i + 1] == 'b') return 0x6b; + if (caractere[i] == '6' && caractere[i + 1] == 'c') return 0x6c; + if (caractere[i] == '6' && caractere[i + 1] == 'd') return 0x6d; + if (caractere[i] == '6' && caractere[i + 1] == 'e') return 0x6e; + if (caractere[i] == '6' && caractere[i + 1] == 'f') return 0x6f; + + if (caractere[i] == '7' && caractere[i + 1] == '0') return 0x70; + if (caractere[i] == '7' && caractere[i + 1] == '1') return 0x71; + if (caractere[i] == '7' && caractere[i + 1] == '2') return 0x72; + if (caractere[i] == '7' && caractere[i + 1] == '3') return 0x73; + if (caractere[i] == '7' && caractere[i + 1] == '4') return 0x74; + if (caractere[i] == '7' && caractere[i + 1] == '5') return 0x75; + if (caractere[i] == '7' && caractere[i + 1] == '6') return 0x76; + if (caractere[i] == '7' && caractere[i + 1] == '7') return 0x77; + if (caractere[i] == '7' && caractere[i + 1] == '8') return 0x78; + if (caractere[i] == '7' && caractere[i + 1] == '9') return 0x79; + if (caractere[i] == '7' && caractere[i + 1] == 'a') return 0x7a; + if (caractere[i] == '7' && caractere[i + 1] == 'b') return 0x7b; + if (caractere[i] == '7' && caractere[i + 1] == 'c') return 0x7c; + if (caractere[i] == '7' && caractere[i + 1] == 'd') return 0x7d; + if (caractere[i] == '7' && caractere[i + 1] == 'e') return 0x7e; + if (caractere[i] == '7' && caractere[i + 1] == 'f') return 0x7f; + + if (caractere[i] == '8' && caractere[i + 1] == '0') return 0x80; + if (caractere[i] == '8' && caractere[i + 1] == '1') return 0x81; + if (caractere[i] == '8' && caractere[i + 1] == '2') return 0x82; + if (caractere[i] == '8' && caractere[i + 1] == '3') return 0x83; + if (caractere[i] == '8' && caractere[i + 1] == '4') return 0x84; + if (caractere[i] == '8' && caractere[i + 1] == '5') return 0x85; + if (caractere[i] == '8' && caractere[i + 1] == '6') return 0x86; + if (caractere[i] == '8' && caractere[i + 1] == '7') return 0x87; + if (caractere[i] == '8' && caractere[i + 1] == '8') return 0x88; + if (caractere[i] == '8' && caractere[i + 1] == '9') return 0x89; + if (caractere[i] == '8' && caractere[i + 1] == 'a') return 0x8a; + if (caractere[i] == '8' && caractere[i + 1] == 'b') return 0x8b; + if (caractere[i] == '8' && caractere[i + 1] == 'c') return 0x8c; + if (caractere[i] == '8' && caractere[i + 1] == 'd') return 0x8d; + if (caractere[i] == '8' && caractere[i + 1] == 'e') return 0x8e; + if (caractere[i] == '8' && caractere[i + 1] == 'f') return 0x8f; + + if (caractere[i] == '9' && caractere[i + 1] == '0') return 0x90; + if (caractere[i] == '9' && caractere[i + 1] == '1') return 0x91; + if (caractere[i] == '9' && caractere[i + 1] == '2') return 0x92; + if (caractere[i] == '9' && caractere[i + 1] == '3') return 0x93; + if (caractere[i] == '9' && caractere[i + 1] == '4') return 0x94; + if (caractere[i] == '9' && caractere[i + 1] == '5') return 0x95; + if (caractere[i] == '9' && caractere[i + 1] == '6') return 0x96; + if (caractere[i] == '9' && caractere[i + 1] == '7') return 0x97; + if (caractere[i] == '9' && caractere[i + 1] == '8') return 0x98; + if (caractere[i] == '9' && caractere[i + 1] == '9') return 0x99; + if (caractere[i] == '9' && caractere[i + 1] == 'a') return 0x9a; + if (caractere[i] == '9' && caractere[i + 1] == 'b') return 0x9b; + if (caractere[i] == '9' && caractere[i + 1] == 'c') return 0x9c; + if (caractere[i] == '9' && caractere[i + 1] == 'd') return 0x9d; + if (caractere[i] == '9' && caractere[i + 1] == 'e') return 0x9e; + if (caractere[i] == '9' && caractere[i + 1] == 'f') return 0x9f; + + if (caractere[i] == 'a' && caractere[i + 1] == '0') return 0xa0; + if (caractere[i] == 'a' && caractere[i + 1] == '1') return 0xa1; + if (caractere[i] == 'a' && caractere[i + 1] == '2') return 0xa2; + if (caractere[i] == 'a' && caractere[i + 1] == '3') return 0xa3; + if (caractere[i] == 'a' && caractere[i + 1] == '4') return 0xa4; + if (caractere[i] == 'a' && caractere[i + 1] == '5') return 0xa5; + if (caractere[i] == 'a' && caractere[i + 1] == '6') return 0xa6; + if (caractere[i] == 'a' && caractere[i + 1] == '7') return 0xa7; + if (caractere[i] == 'a' && caractere[i + 1] == '8') return 0xa8; + if (caractere[i] == 'a' && caractere[i + 1] == '9') return 0xa9; + if (caractere[i] == 'a' && caractere[i + 1] == 'a') return 0xaa; + if (caractere[i] == 'a' && caractere[i + 1] == 'b') return 0xab; + if (caractere[i] == 'a' && caractere[i + 1] == 'c') return 0xac; + if (caractere[i] == 'a' && caractere[i + 1] == 'd') return 0xad; + if (caractere[i] == 'a' && caractere[i + 1] == 'e') return 0xae; + if (caractere[i] == 'a' && caractere[i + 1] == 'f') return 0xaf; + + if (caractere[i] == 'b' && caractere[i + 1] == '0') return 0xb0; + if (caractere[i] == 'b' && caractere[i + 1] == '1') return 0xb1; + if (caractere[i] == 'b' && caractere[i + 1] == '2') return 0xb2; + if (caractere[i] == 'b' && caractere[i + 1] == '3') return 0xb3; + if (caractere[i] == 'b' && caractere[i + 1] == '4') return 0xb4; + if (caractere[i] == 'b' && caractere[i + 1] == '5') return 0xb5; + if (caractere[i] == 'b' && caractere[i + 1] == '6') return 0xb6; + if (caractere[i] == 'b' && caractere[i + 1] == '7') return 0xb7; + if (caractere[i] == 'b' && caractere[i + 1] == '8') return 0xb8; + if (caractere[i] == 'b' && caractere[i + 1] == '9') return 0xb9; + if (caractere[i] == 'b' && caractere[i + 1] == 'a') return 0xba; + if (caractere[i] == 'b' && caractere[i + 1] == 'b') return 0xbb; + if (caractere[i] == 'b' && caractere[i + 1] == 'c') return 0xbc; + if (caractere[i] == 'b' && caractere[i + 1] == 'd') return 0xbd; + if (caractere[i] == 'b' && caractere[i + 1] == 'e') return 0xbe; + if (caractere[i] == 'b' && caractere[i + 1] == 'f') return 0xbf; + + if (caractere[i] == 'c' && caractere[i + 1] == '0') return 0xc0; + if (caractere[i] == 'c' && caractere[i + 1] == '1') return 0xc1; + if (caractere[i] == 'c' && caractere[i + 1] == '2') return 0xc2; + if (caractere[i] == 'c' && caractere[i + 1] == '3') return 0xc3; + if (caractere[i] == 'c' && caractere[i + 1] == '4') return 0xc4; + if (caractere[i] == 'c' && caractere[i + 1] == '5') return 0xc5; + if (caractere[i] == 'c' && caractere[i + 1] == '6') return 0xc6; + if (caractere[i] == 'c' && caractere[i + 1] == '7') return 0xc7; + if (caractere[i] == 'c' && caractere[i + 1] == '8') return 0xc8; + if (caractere[i] == 'c' && caractere[i + 1] == '9') return 0xc9; + if (caractere[i] == 'c' && caractere[i + 1] == 'a') return 0xca; + if (caractere[i] == 'c' && caractere[i + 1] == 'b') return 0xcb; + if (caractere[i] == 'c' && caractere[i + 1] == 'c') return 0xcc; + if (caractere[i] == 'c' && caractere[i + 1] == 'd') return 0xcd; + if (caractere[i] == 'c' && caractere[i + 1] == 'e') return 0xce; + if (caractere[i] == 'c' && caractere[i + 1] == 'f') return 0xcf; + + if (caractere[i] == 'd' && caractere[i + 1] == '0') return 0xd0; + if (caractere[i] == 'd' && caractere[i + 1] == '1') return 0xd1; + if (caractere[i] == 'd' && caractere[i + 1] == '2') return 0xd2; + if (caractere[i] == 'd' && caractere[i + 1] == '3') return 0xd3; + if (caractere[i] == 'd' && caractere[i + 1] == '4') return 0xd4; + if (caractere[i] == 'd' && caractere[i + 1] == '5') return 0xd5; + if (caractere[i] == 'd' && caractere[i + 1] == '6') return 0xd6; + if (caractere[i] == 'd' && caractere[i + 1] == '7') return 0xd7; + if (caractere[i] == 'd' && caractere[i + 1] == '8') return 0xd8; + if (caractere[i] == 'd' && caractere[i + 1] == '9') return 0xd9; + if (caractere[i] == 'd' && caractere[i + 1] == 'a') return 0xda; + if (caractere[i] == 'd' && caractere[i + 1] == 'b') return 0xdb; + if (caractere[i] == 'd' && caractere[i + 1] == 'c') return 0xdc; + if (caractere[i] == 'd' && caractere[i + 1] == 'd') return 0xdd; + if (caractere[i] == 'd' && caractere[i + 1] == 'e') return 0xde; + if (caractere[i] == 'd' && caractere[i + 1] == 'f') return 0xdf; + + if (caractere[i] == 'e' && caractere[i + 1] == '0') return 0xe0; + if (caractere[i] == 'e' && caractere[i + 1] == '1') return 0xe1; + if (caractere[i] == 'e' && caractere[i + 1] == '2') return 0xe2; + if (caractere[i] == 'e' && caractere[i + 1] == '3') return 0xe3; + if (caractere[i] == 'e' && caractere[i + 1] == '4') return 0xe4; + if (caractere[i] == 'e' && caractere[i + 1] == '5') return 0xe5; + if (caractere[i] == 'e' && caractere[i + 1] == '6') return 0xe6; + if (caractere[i] == 'e' && caractere[i + 1] == '7') return 0xe7; + if (caractere[i] == 'e' && caractere[i + 1] == '8') return 0xe8; + if (caractere[i] == 'e' && caractere[i + 1] == '9') return 0xe9; + if (caractere[i] == 'e' && caractere[i + 1] == 'a') return 0xea; + if (caractere[i] == 'e' && caractere[i + 1] == 'b') return 0xeb; + if (caractere[i] == 'e' && caractere[i + 1] == 'c') return 0xec; + if (caractere[i] == 'e' && caractere[i + 1] == 'd') return 0xed; + if (caractere[i] == 'e' && caractere[i + 1] == 'e') return 0xee; + if (caractere[i] == 'e' && caractere[i + 1] == 'f') return 0xef; + + if (caractere[i] == 'f' && caractere[i + 1] == '0') return 0xf0; + if (caractere[i] == 'f' && caractere[i + 1] == '1') return 0xf1; + if (caractere[i] == 'f' && caractere[i + 1] == '2') return 0xf2; + if (caractere[i] == 'f' && caractere[i + 1] == '3') return 0xf3; + if (caractere[i] == 'f' && caractere[i + 1] == '4') return 0xf4; + if (caractere[i] == 'f' && caractere[i + 1] == '5') return 0xf5; + if (caractere[i] == 'f' && caractere[i + 1] == '6') return 0xf6; + if (caractere[i] == 'f' && caractere[i + 1] == '7') return 0xf7; + if (caractere[i] == 'f' && caractere[i + 1] == '8') return 0xf8; + if (caractere[i] == 'f' && caractere[i + 1] == '9') return 0xf9; + if (caractere[i] == 'f' && caractere[i + 1] == 'a') return 0xfa; + if (caractere[i] == 'f' && caractere[i + 1] == 'b') return 0xfb; + if (caractere[i] == 'f' && caractere[i + 1] == 'c') return 0xfc; + if (caractere[i] == 'f' && caractere[i + 1] == 'd') return 0xfd; + if (caractere[i] == 'f' && caractere[i + 1] == 'e') return 0xfe; + if (caractere[i] == 'f' && caractere[i + 1] == 'f') return 0xff; + + return 0x00; +} diff --git a/owlps-positioning/positioning.cc b/owlps-positioning/positioning.cc new file mode 100644 index 0000000..3b0dfd3 --- /dev/null +++ b/owlps-positioning/positioning.cc @@ -0,0 +1,651 @@ +#include "positioning.hh" + +template +inline T from_string(const string &s) +{ + + T t; + istringstream iss(s); + + iss >> t; + + return t; +} + +inline float round_float(float f, int n) +{ + n = (int) pow((double) 10, (double) n) ; + float f_dec = modff(f, &f) ; + f_dec = floor(f_dec * n) / n ; + + return f + f_dec ; +} + +inline vector explode(const string &input, const char &sep) +{ + vector vs; + string tmp; + unsigned int i; + + for (i = 0 ; i < input.size() ; i++) + if (input[i] == sep) + { + vs.push_back(tmp); + tmp.clear(); + } + else + { + tmp.push_back(input[i]); + } + + vs.push_back(tmp); + tmp.clear(); + + return vs; +} + +inline vector extractReferencePointInfoFromBuffer(const string &buffer_in) +{ + unsigned int i = 0; + string tmp_field; + vector ret; + + while (buffer_in[i] != ';') + { + tmp_field.push_back(buffer_in[i]); + i++; + } + ret.push_back(tmp_field); + tmp_field.clear(); + i++; // go after the ';' + + while (buffer_in[i] != ';') + { + tmp_field.push_back(buffer_in[i]); + i++; + } + ret.push_back(tmp_field); + tmp_field.clear(); + i++; + + while (buffer_in[i] != ';') + { + tmp_field.push_back(buffer_in[i]); + i++; + } + ret.push_back(tmp_field); + tmp_field.clear(); + i++; + + while (buffer_in[i] != ';') + { + tmp_field.push_back(buffer_in[i]); + i++; + } + ret.push_back(tmp_field); + tmp_field.clear(); + i++; + + while (i <= buffer_in.size()) + { + if ((buffer_in[i] == ';' || i == buffer_in.size()) && !tmp_field.empty()) // Si on est sur un séparateur et que la valeur lue n'est pas vide, + { + ret.push_back(tmp_field) ; // on met la valeur lue dans les valeurs de retour. + tmp_field.clear() ; + } + else // Si on n'est pas sur un séparateur, + tmp_field.push_back(buffer_in[i]) ; // on ajoute le caractère courant à la suite de la valeur lue. + + i++ ; + } + + return ret; +} + +void Positioning::makeReferencePointListFromFile(const string &filename, const bool uniq_point) +{ + + ifstream input_file ; // Flux d'entrée du fichier. + string cpp_buffer ; // Buffer au format string. + ReferencePoint rp; + Point tmp_point; + float x, y, z ; // Coordonnées des points. + unsigned int pt_idx = 0 ; // Position du point lu dans la liste. + vector infos ; // Liste des informations lues dans une ligne du fichier. + + input_file.open(filename.c_str()) ; + if (input_file.fail()) + { + cerr << "Error opening input file « " << filename << " » !" << endl ; + return ; + } + + while (!input_file.eof()) + { + getline(input_file, cpp_buffer); + + if ((input_file.rdstate() & ifstream::eofbit) == 0) + { + if (cpp_buffer.size() == 0) // Ignorer une ligne vide + continue ; + + infos = extractReferencePointInfoFromBuffer(cpp_buffer); + x = from_string(infos[0]); + y = from_string(infos[1]); + z = from_string(infos[2]); + + tmp_point.setX(x); + tmp_point.setY(y); + tmp_point.setZ(z); + + if (!uniq_point || !pointExists(reference_point_list, tmp_point)) // Si on ne veut pas de points unique, ou que le point n'existe pas encore,{ + { + rp.setCoordinates(tmp_point); + reference_point_list.push_back(rp); // on le crée. + pt_idx = reference_point_list.size() - 1; // Le point que l'on vient d'ajouter est le dernier du vector. + } + else // Le point existe déjà : + { + pt_idx = pointIndex(reference_point_list, tmp_point) ; // On recherche le point auquel on veut ajouter les informations. + } + + for (unsigned int i = 4; i < infos.size(); i++) + { + if (i+1 < infos.size()) + { + reference_point_list[pt_idx].addMeasurement(infos[i], from_string(infos[i+1])); + i++; + } + } + } + } + + input_file.close(); + infos.clear() ; +} + +void Positioning::makeApListFromFile(const string &filename) +{ + + ifstream input_file; + string buffer; + vector ap_infos; + AccessPoint tmp_ap; + + input_file.open(filename.c_str()); + if (input_file.fail()) + { + cerr << "Error opening input file « " << filename << " » !" << endl ; + return ; + } + + while (!input_file.eof()) + { + getline(input_file, buffer); + + if ((input_file.rdstate() & ifstream::eofbit) == 0) + { + if (buffer[0] == '\0' || buffer[0] == '#') // ligne vide ou ligne commençant par # + continue; + + ap_infos = explode(buffer, ';'); + tmp_ap.setApAddr(ap_infos[0]); + tmp_ap.setCoordinates(from_string(ap_infos[1]), from_string(ap_infos[2]), from_string(ap_infos[3])); + tmp_ap.setFrequency(from_string(ap_infos[4])); + tmp_ap.setAntennaGain(from_string(ap_infos[5])); + tmp_ap.setOutputPower(from_string(ap_infos[6])); + access_point_list.push_back(tmp_ap); + ap_infos.clear(); + } + } + + input_file.close(); +} + +void Positioning::makeTopologyFromFile(const string &filename) +{ + + ifstream input_file; + string buffer; + vector infos; + + input_file.open(filename.c_str()) ; + if (input_file.fail()) + { + cerr << "Error opening input file « " << filename << " » !" << endl ; + return ; + } + + while (!input_file.eof()) + { + getline(input_file, buffer) ; + + if ((input_file.rdstate() & ifstream::eofbit) == 0) + { + /* Traitement basique des commentaires */ + if (buffer[0] == '\0' || buffer[0] == '#') // ligne vide ou ligne commençant par # + continue ; // ignorer cette ligne. + + infos = explode(buffer, ';') ; + if (area_list.find(infos[0]) != area_list.end()) // Si la pièce existe déjà, + cerr << "Erreur ! Déclaration multiple de la zone « " << infos[0] << " »." << endl ; // on le signale ; + else // sinon on l'ajoute : + area_list[infos[0]] = Area(infos[0], from_string(infos[1]), from_string(infos[3]), + from_string(infos[2]), from_string(infos[4]), + from_string(infos[5]), from_string(infos[6])) ; + + infos.clear() ; + } + } + + input_file.close() ; + +} + +void Positioning::makeWaypointListFromFile(const string &filename) +{ + + ifstream input_file ; + string buffer; + vector infos ; + set point_list ; + + input_file.open(filename.c_str()); + if (input_file.fail()) + { + cerr << "Error opening input file « " << filename << " » !" << endl ; + return ; + } + + while (!input_file.eof()) + { + getline(input_file, buffer); + + if ((input_file.rdstate() & ifstream::eofbit) == 0) + { + if (buffer[0] == '\0' || buffer[0] == '#') // ligne vide ou ligne commençant par # + continue; + + infos = explode(buffer, ';') ; + + Point tmp_pt(from_string(infos[0]), from_string(infos[1]), from_string(infos[2])) ; + if (! point_list.insert(tmp_pt).second) + cerr << "Point " << tmp_pt << " non ajouté ! Peut-être est-il dupliqué ?" << endl ; + + infos.clear() ; + } + } + input_file.close() ; // Lecture du fichier terminée + + + unsigned int nb_pts = point_list.size() ; // Nombre de points + unsigned int cur_idx = 0 ; // Itérateur sur l'indice de la matrice. + waypoint_list.reserve(nb_pts) ; // Vector contenant tous les points (attribut du serveur) + waypoint_matrix = new float*[nb_pts] ; // Matrice (carrée) des distances entre les points de passage (attribut du serveur) + for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : + { + waypoint_matrix[i] = new float[nb_pts] ; + for (unsigned int k = 0 ; k < nb_pts ; k++) // Initialisation des distances à -1 + waypoint_matrix[i][k] = -1 ; + } + + for (set::iterator it = point_list.begin() ; it != point_list.end() ; it++, cur_idx++) // Pour chaque point enregistré + { + waypoint_list.push_back(*it) ; // Ajout du point dans waypoint_list + waypoint_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle + + for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent + { + if (inTheSameArea(waypoint_list[cur_idx], waypoint_list[k])) // Si le point est dans la même zone, + { + float dist = it->distance(waypoint_list[k]) ; // on calcule la distance + waypoint_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, + waypoint_matrix[k][cur_idx] = dist ; // dans les deux sens. + } + } + } + + bool comput_done = true ; + while (comput_done) + { + comput_done = false ; + for (unsigned int i = 0 ; i < nb_pts ; i++) + for (unsigned int j = 0 ; j < nb_pts ; j++) + if (waypoint_matrix[i][j] > 0) + for (unsigned int k = 0 ; k < nb_pts ; k++) + if (waypoint_matrix[j][k] > 0) + { + float tmp_dist = round_float((waypoint_matrix[j][k] + waypoint_matrix[i][j]), 2); + if (tmp_dist < round_float(waypoint_matrix[i][k], 2) || waypoint_matrix[i][k] == -1) + { + waypoint_matrix[i][k] = tmp_dist ; + comput_done = true ; + } + } + } +} + +map Positioning::inWhichAreas(const Point &p) +{ + + map areas ; + + for (map::iterator it = area_list.begin() ; it != area_list.end() ; it++) + if (it->second.containsPoint(p)) + areas.insert(make_pair(it->first, it->second)) ; + + return areas ; +} + +bool Positioning::inTheSameArea(const Point &p1, const Point &p2) +{ + + // Liste des zones comportant les points p1 et p2 : + map zones1(inWhichAreas(p1)); + map zones2(inWhichAreas(p2)); + + if (zones1.size() == 0 || zones2.size() == 0) + { + return false; + } + + for (map::iterator it1 = zones1.begin() ; it1 != zones1.end() ; it1++) // Parcours des zones : + for (map::iterator it2 = zones2.begin(); it2 != zones2.end(); it2++) + if (it1->second == it2->second) + { + return true; + } + + return false ; +} + +float Positioning::distanceTopology(const Point &p1, const Point &p2) +{ + + map zones1(inWhichAreas(p1)); + map zones2(inWhichAreas(p2)); + + if (zones1.size() == 0 || zones2.size() == 0) // Si aucune zone ne contient p1 ou p2, + { + return -1; + } + + Area z1(zones1.begin() -> second); // Première zone d'appartenance du point p1. // FIXME : vérifier toutes les zones + Area z2(zones2.begin() -> second); + vector connection; + + + /* *** Cas de la même zone *** */ + if (z1 == z2) // Si les points sont dans la même zone, + { + return p1.distance(p2) ; // la distance entre eux est la distance euclidienne. + } + + + /* *** Cas de deux zones voisines (connectées directement) *** */ + if ((connection = areaConnection(z1, z2)).size() != 0) // Si les points sont dans deux zones voisines, + { + // la distance entre eux est la distance euclidienne de chacun jusqu'au plus proche point de passage entre les deux zones. + float dist = p1.distance(connection[0]) + p2.distance(connection[0]) ; + for (unsigned int i = 1 ; i < connection.size() ; i++) // Recherche du point de passage offrant la plus courte distance + { + float tmp_dist = p1.distance(connection[i]) + p2.distance(connection[i]) ; + if (tmp_dist < dist) + dist = tmp_dist ; + } + + return dist ; + } + + + /* *** Les points sont dans des zones non-voisines *** */ + // Liste des points de passage appartenant respectivement à z1 et à z2. + vector wp_z1(areaConnection(z1)); + vector wp_z2(areaConnection(z2)); + + // Indices des points de passage dans la liste : + int wp_z1_idx; + int wp_z2_idx = -1 ; // z2 ne peut pas être utilisé non initialisé, contrairement à ce que dit GCC, car dans le cas où il n'est pas initialisé on quitte la fonction avant de l'utiliser (cf. "return -1" un peu plus bas); + + if (wp_z1.size() == 0 || wp_z2.size() == 0) // Si l'une des deux zones ne comporte aucun point de passage, + { + return -1 ; // on quitte (ceci ne devrait jamais se produire). + } + + /* Première itération (voir explication de l'algorithme plus bas) */ + unsigned int i1, i2 ; + for (i1 = 0 ; i1 < wp_z1.size() ; i1++) // Recherche des premiers indices valides (où il existe un chemin entre les points de passage) + { + wp_z1_idx = pointIndex(waypoint_list, wp_z1[i1]) ; + for (i2 = 0 ; i2 < wp_z2.size() ; i2++) + { + wp_z2_idx = pointIndex(waypoint_list, wp_z2[i2]) ; + if (wp_z2_idx < 0) + continue ; + + if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, + break ; // on arrête le parcours. + } + if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, + break ; // on arrête le parcours. + } + + if (i1 >= wp_z1.size()) // Si on a parcouru tout le tableau sans trouver de chemin, + { + return -1 ; // on quitte. + } + + float dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[i2]); + float tmp_dist ; + + for (unsigned int j = i2 + 1 ; j < wp_z2.size() ; j++) // Fin du parcours : + { + wp_z2_idx = pointIndex(waypoint_list, wp_z2[j]) ; + if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) + continue ; + tmp_dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; + if (tmp_dist < dist) + dist = tmp_dist ; + } + + /* Itérations suivantes */ + for (unsigned int i = i1 + 1 ; i < wp_z1.size() ; i++) + for (unsigned int j = 0 ; j < wp_z2.size() ; j++) + { + // Indice des points de passage wp_z1[i] et wp_z2[j] dans la liste des points de passage : + wp_z1_idx = pointIndex(waypoint_list, wp_z1[i]) ; + wp_z2_idx = pointIndex(waypoint_list, wp_z2[j]) ; + + if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) // S'il n'existe aucun chemin entre les deux points de passage + continue ; + + tmp_dist = p1.distance(wp_z1[i]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; + if (tmp_dist < dist) + dist = tmp_dist ; + } + + return dist ; +} + +vector Positioning::areaConnection(const Area &z1, const Area &z2) +{ + vector points ; + + for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) + { + map areas(inWhichAreas(waypoint_list[i])) ; + if (areas.find(z1.getName()) != areas.end() && areas.find(z2.getName()) != areas.end()) + points.push_back(waypoint_list[i]) ; + } + + return points ; +} + + + +vector Positioning::areaConnection(const Area &z) +{ + vector points ; + + for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) + { + map areas(inWhichAreas(waypoint_list[i])) ; + if (areas.find(z.getName()) != areas.end()) + points.push_back(waypoint_list[i]) ; + } + + return points ; +} + +void Positioning::makeReferencePointDistances() +{ + + unsigned int nb_pts = reference_point_list.size() ; // Nombre de points à traiter. + + reference_point_matrix = new float*[nb_pts] ; // Allocation de la première dimension. + for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : + { + reference_point_matrix[i] = new float[nb_pts] ; + for (unsigned int k = 0; k < nb_pts; k++) // Initialisation des distances à -1 + reference_point_matrix[i][k] = -1 ; + } + + for (unsigned int cur_idx = 0 ; cur_idx < nb_pts ; cur_idx++) + { + reference_point_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle + + for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent + { + float dist = distanceTopology((Point) reference_point_list[cur_idx], (Point) reference_point_list[k]) ; // On calcule la distance + reference_point_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, + reference_point_matrix[k][cur_idx] = dist ; // dans les deux sens. + } + } +} + +bool Positioning::checkTopology() +{ + + for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) + { + map areas(inWhichAreas(waypoint_list[i])) ; + if (areas.empty()) + { + return false ; + } + } + + + for (unsigned int i = 0 ; i < reference_point_list.size() ; i++) + { + map areas(inWhichAreas((Point)reference_point_list[i])) ; + if (areas.empty()) + { + return false ; // À modifier si on veut permettre aux points de référence de n'appartenir à aucune zone. + } + } + + + set connected_areas ; // Liste des zones connectées à au moins une autre zone (on n'enregistre que le nom des zones, dupliquer toutes les zones étant inutile). + + for (map::iterator it1 = area_list.begin() ; it1 != area_list.end() ; it1++) + for (map::iterator it2 = area_list.begin() ; it2 != area_list.end() ; it2++) + { + if (it1 == it2) + continue ; + + vector connect(areaConnection(it1->second, it2->second)) ; + if (!connect.empty()) + connected_areas.insert(it1->first) ; // Ajout de la zone à la liste des zones connectées. + } + + if (connected_areas.size() != area_list.size()) + { + return false ; + } + + return true ; +} + +inline bool Positioning::pointExists(const float &x, const float &y, const float &z) const + { + return pointExists(reference_point_list, Point(x, y, z)); + } + +inline bool Positioning::pointExists(const Point &p) const + { + return pointExists(reference_point_list, p); + } + +inline bool Positioning::pointExists(const vector &point_list, const float &x, const float &y, const float &z) const + { + return pointExists(point_list, Point(x, y, z)); + } + +inline bool Positioning::pointExists(const vector &point_list, const Point &p) const + { + return (pointIndex(point_list, p) != -1); + } + +inline int Positioning::pointIndex(const Point &p) const + { + return (unsigned int) pointIndex(reference_point_list, p); + } + +inline int Positioning::pointIndex(const vector &point_list, const float &x, const float &y, const float &z) const + { + return (unsigned int) pointIndex(point_list, Point(x, y, z)) ; + } + +inline int Positioning::pointIndex(const vector &point_list, const Point &p) const + { + unsigned int i; + + for (i = 0 ; i < point_list.size() ; i++) + if (p == point_list[i].getCoordinates()) + { + return i; + } + + return -1; + } + +/* Retourne la position du Point "p" dans le tableau à une dimension "point_tab" de taille "size", ou -1 en cas d'échec. */ +inline int Positioning::pointIndex(const Point *point_tab, unsigned int &size, const Point &p) const + { + for (unsigned int i = 0 ; i < size ; i++) + if (point_tab[i] == p) + return i; + + return -1; + } + +/* Retourne la position du Point "p" dans le vector "point_list", ou -1 en cas d'échec. */ +inline int Positioning::pointIndex(const vector &point_list, const Point &p) const + { + + for (unsigned int i = 0 ; i < point_list.size() ; i++) + if (point_list[i] == p) + { + return i; + } + + return -1; + } + +void Positioning::printReferencePointList() +{ + printPointList(reference_point_list) ; +} + +void Positioning::printPointList(vector &point_list) +{ + for (unsigned int i = 0 ; i < point_list.size() ; i++) + cout << point_list[i] << endl ; +} + +void Positioning::printAccessPointList() const + { + for (unsigned int i = 0; i < access_point_list.size(); i++) + cout << access_point_list[i] << endl; + } diff --git a/owlps-positioning/positioning.hh b/owlps-positioning/positioning.hh new file mode 100644 index 0000000..36093d8 --- /dev/null +++ b/owlps-positioning/positioning.hh @@ -0,0 +1,84 @@ +#ifndef _POSITIONING_HH_ +#define _POSITIONING_HH_ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "referencepoint.hh" +#include "point.hh" +#include "accesspoint.hh" +#include "area.hh" + +using namespace std; + +class Positioning + { + + private: + vector reference_point_list; // Liste des points de référence (calibration). + float** reference_point_matrix; // Matrice des distances entre les points de référence. + vector access_point_list; // Liste des AP connus. + vector waypoint_list; // Liste des points de passage entre les zones. + float** waypoint_matrix; // Matrice des distances entre les points de passage. + map area_list ; // Liste des zones homogènes (pièces). + + public : + + Positioning() {}; + ~Positioning() {}; + + void makeReferencePointListFromFile(const string &filename, const bool); + void makeApListFromFile(const string &filename); + void makeTopologyFromFile(const string &filename); + void makeWaypointListFromFile(const string &filename); + + void makeReferencePointListFromDb() {}; + void makeApListFromDb() {}; + void makeTopologyFromDb() {}; + void makeWaypointListFromDb() {}; + + map inWhichAreas(const Point &p); + bool inTheSameArea(const Point &p1, const Point &p2); + float distanceTopology(const Point &p1, const Point &p2); + vector areaConnection(const Area &z1, const Area &z2); + vector areaConnection(const Area &z); + + void makeReferencePointDistances(); + bool checkTopology(); + + bool pointExists(const float &x, const float &y, const float &z)const; + bool pointExists(const Point &p)const; + bool pointExists(const vector &point_list, const float &x, const float &y, const float &z) const ; + bool pointExists(const vector &point_list, const Point &p) const ; + + int pointIndex(const float &x, const float &y, const float &z) const; + int pointIndex(const Point &p) const; + int pointIndex(const vector &point_list, const float &x, const float &y, const float &z) const ; + int pointIndex(const vector &point_list, const Point &p) const ; + int pointIndex(const Point *tab, unsigned int &size, const Point &p) const ; + int pointIndex(const vector &point_list, const Point &p) const ; + + vector getAccessPointList() const + { + return access_point_list; + }; + vector getReferencePointList() const + { + return reference_point_list; + }; + + void printReferencePointList(); + void printPointList(vector &point_list); + void printAccessPointList() const; + }; + +#endif diff --git a/owlps-positioning/server.cc b/owlps-positioning/server.cc index d8597ab..0e9bc75 100644 --- a/owlps-positioning/server.cc +++ b/owlps-positioning/server.cc @@ -1,2652 +1,153 @@ #include "server.hh" - - -/******* Misc. very usefull functions *******/ - - - - -/* Tronque le float "f" à "n" décimales et le retourne */ -inline float round_float(float f, int n) +char* mac_bytes_to_string(unsigned char *mac_binary) { - n = (int) pow((double) 10, (double) n) ; - float f_dec = modff(f, &f) ; - f_dec = floor(f_dec * n) / n ; + char *ret = (char *)malloc(sizeof(char) * 18) ; - return f + f_dec ; -} - - - -/* Tronque le float "f" à 2 décimales et le retourne */ -inline float round_float_2(float f) -{ - return round_float(f, 2) ; -} - - - -/* Explodes a string into substrings based on separator sep. Returns a string vector. */ -inline vector explode(const string &input, const char &sep) -{ - vector vs; - string tmp; - unsigned int i; - - for (i = 0 ; i < input.size() ; i++) - if (input[i] == sep) - { - vs.push_back(tmp); - tmp.clear(); - } - else - { - tmp.push_back(input[i]); - } - - //Last entry, did not encounter a separator. - vs.push_back(tmp); - tmp.clear(); - - return vs; -} - - - -/* Function to convert a string to an integer */ -inline int string2int(const string &nb) -{ - istringstream iss(nb); - - int tmp; - iss >> tmp; - return tmp; -} - - - -/* Function to convert a string to an unsigned integer */ -inline unsigned int string2uint(const string &nb) -{ - istringstream iss(nb); - - unsigned int tmp; - iss >> tmp; - return tmp; -} - - - -/* Function to convert a string to a float */ -inline float string2float(const string &nb) -{ - istringstream iss(nb); - - float tmp; - iss >> tmp; - return tmp; -} - - - -/* Function extracts ints from string */ -inline vector extractValues(string buff) -{ - unsigned int ptr = 0; - vector ret; - string tmp_field; - - if (buff[buff.size()-1] != ';') - buff.push_back(';'); - - while (ptr < buff.size()) - { - if (buff[ptr] != ';') - tmp_field.push_back(buff[ptr]); - else - { - ret.push_back(string2int(tmp_field)); - tmp_field.clear(); - } - ptr++; - } - return ret; -} - - - -inline vector extractReferencePointInfoFromBuffer(const string &buffer_in) -{ - unsigned int i = 0; - string tmp_field; - vector ret; - - /* Extract coordinates */ - /* x */ - while (buffer_in[i] != ';') - { - tmp_field.push_back(buffer_in[i]); - i++; - } - ret.push_back(tmp_field); - tmp_field.clear(); - i++; // go after the ';' - - /* y */ - while (buffer_in[i] != ';') - { - tmp_field.push_back(buffer_in[i]); - i++; - } - ret.push_back(tmp_field); - tmp_field.clear(); - i++; - -#ifndef FRED_CSV_FORMAT // Dans le format Fred, on n'a pas de coordonnée Z. - /* z */ - while (buffer_in[i] != ';') - { - tmp_field.push_back(buffer_in[i]); - i++; - } - ret.push_back(tmp_field); - tmp_field.clear(); - i++; -#endif // FRED_CSV_FORMAT - - /* Extract direction (not used now) */ - while (buffer_in[i] != ';') - { - tmp_field.push_back(buffer_in[i]); - i++; - } - ret.push_back(tmp_field); - tmp_field.clear(); - i++; - -#ifdef FRED_CSV_FORMAT - /* Extract mac address */ - while (buffer_in[i] != ';') - { - tmp_field.push_back(buffer_in[i]); - i++; - } - ret.push_back(tmp_field); - tmp_field.clear(); - i++; - - /* Extract scan list */ - while (i < buffer_in.size()) - { - tmp_field.push_back(buffer_in[i]); - i++; - } - ret.push_back(tmp_field); - tmp_field.clear(); -#else // FRED_CSV_FORMAT - while (i <= buffer_in.size()) - { - if ((buffer_in[i] == ';' || i == buffer_in.size()) && !tmp_field.empty()) // Si on est sur un séparateur et que la valeur lue n'est pas vide, - { -#ifdef DEBUG_2 - cout << "Ajout de la valeur lue : " << tmp_field << endl ; -#endif // DEBUG_2 - ret.push_back(tmp_field) ; // on met la valeur lue dans les valeurs de retour. - tmp_field.clear() ; - } - else // Si on n'est pas sur un séparateur, - tmp_field.push_back(buffer_in[i]) ; // on ajoute le caractère courant à la suite de la valeur lue. - - i++ ; - } -#endif // FRED_CSV_FORMAT - - /* Return the vector with each data */ - return ret; -} - - - -/* ***************************************************************** */ - - - -//Server::Server(string ip_addr, int listen_port, int send_port) // FIXME : paramètre send_port inutilisé -Server::Server(const string &ap_file, const string &ref_pt_file, const string &ip_addr, const int &listen_port) -{ -#ifdef DEBUG_T - cout << "//--> Server::Server()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - /* Open socket */ - sockListen = socket(PF_INET, SOCK_DGRAM, 0); - sockSend = socket(PF_INET, SOCK_DGRAM, 0); - - /* Set addr */ - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(listen_port); - server_addr.sin_addr.s_addr = inet_addr(ip_addr.c_str()); - memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero)); - - /* Bind */ - bind(sockListen, (struct sockaddr *)&server_addr, sizeof(server_addr)); - - makeTopologyFromFile(DEFAULT_TOPOLOGY_FILE) ; // Initialisation de "area_list". - makeWaypointListFromFile(DEFAULT_WAYPOINT_FILE) ; // Initialisation de "waypoint_list" et "waypoint_matrix". - makeReferencePointListFromFile(ref_pt_file.c_str()) ; // Initialisation de "reference_point_list". - - /* *** À commenter pour utiliser les mesures centrées mobile de Fred */ - if (! checkTopology()) // Vérifications. - { - cerr << "Topology flawed. Exiting program." << endl ; - exit(1) ; // Si problème, on quitte. - } - /* Fin du bloc à commenter *** */ - - makeReferencePointDistances() ; // Initialisation de "reference_point_matrix". - makeApListFromFile(ap_file.c_str()) ; // Initialisation de "access_point_list". - -#ifdef DEBUG_T - cout << "//<-- Server::Server()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -Server::~Server() -{ -#ifdef DEBUG_T - cout << "//--> Server::~Server()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - close(sockListen); - close(sockSend); - reference_point_list.clear(); - access_point_list.clear(); - client_list.clear(); - -#ifdef DEBUG_T - cout << "//<-- Server::~Server()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -void Server::send_to_client(const int &cl) -{ - /* Do not forget to implement later: usefull for a demo */ -} - - - -int Server::receive_data() -{ - /* Do not forget to implement later: usefull for a demo */ - return 0; -} - - - -/* Cherche dans quelle(s) zone(s) se situe un point. - * Retourne une map contenant la liste des zones auxquelles le Point "p" appartient. - */ -map Server::inWhichAreas(const Point &p) -{ -#ifdef DEBUG_T - cout << "//--> Server::inWhichAreas()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - map areas ; - - for (map::iterator it = area_list.begin() ; it != area_list.end() ; it++) - if (it->second.containsPoint(p)) - areas.insert(make_pair(it->first, it->second)) ; - -#ifdef DEBUG_T - cout << "//<-- Server::inWhichAreas()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return areas ; -} - - - -/* Retourne true si les points "p1" et "p2" sont dans la même zone (ou ont au moins une zone en commun s'ils appartiennent à plusieurs zones). - */ -bool Server::inTheSameArea(const Point &p1, const Point &p2) -{ -#ifdef DEBUG_T - cout << "//--> Server::inTheSameArea()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - map // Liste des zones comportant les points p1 et p2 : - zones1(inWhichAreas(p1)), - zones2(inWhichAreas(p2)) ; - -#ifdef DEBUG_2 - cout << " zones1 (" << zones1.size() << ") : [" ; - for (map::iterator it1 = zones1.begin() ; it1 != zones1.end() ; it1++) - cout << it1->first << ',' ; - cout << "\b]" ; - cout << " zones2 (" << zones2.size() << ") : [" ; - for (map::iterator it1 = zones2.begin() ; it1 != zones2.end() ; it1++) - cout << it1->first << ',' ; - cout << "\b]" ; -#endif // DEBUG_2 - - if (zones1.size() == 0 || zones2.size() == 0) // Si aucune zone ne contient p1 ou p2, - { -#ifdef DEBUG_T - cout << "//<-- Server::inTheSameArea()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return false ; // on quitte. - } - - for (map::iterator it1 = zones1.begin() ; it1 != zones1.end() ; it1++) // Parcours des zones : - for (map::iterator it2 = zones2.begin() ; it2 != zones2.end() ; it2++) - if (it1->second == it2->second) // Si les deux zones sont identiques, - { -#ifdef DEBUG_T - cout << "//<-- Server::inTheSameArea()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return true ; // p1 et p2 sont dans la même zone. - } - -#ifdef DEBUG_T - cout << "//<-- Server::inTheSameArea()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return false ; -} - - - -/* Cherche les points de passage communs aux zones "z1" et "z2". - * Retourne un vector contenant la liste de ces points. - */ -vector Server::areaConnection(const Area &z1, const Area &z2) -{ -#ifdef DEBUG_T - cout << "//--> Server::areaConnection(Area&, Area&)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - vector points ; - - for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) - { - map areas(inWhichAreas(waypoint_list[i])) ; - if (areas.find(z1.getName()) != areas.end() && areas.find(z2.getName()) != areas.end()) - points.push_back(waypoint_list[i]) ; - } - -#ifdef DEBUG_T - cout << "//<-- Server::areaConnection(Area&, Area&)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return points ; -} - - - -/* Cherche les points de passage de la zone "z". - * Retourne un vector contenant la liste de ces points. - */ -vector Server::areaConnection(const Area &z) -{ -#ifdef DEBUG_T - cout << "//--> Server::areaConnection(Area&)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - vector points ; - - for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) - { - map areas(inWhichAreas(waypoint_list[i])) ; - if (areas.find(z.getName()) != areas.end()) - points.push_back(waypoint_list[i]) ; - } - -#ifdef DEBUG_T - cout << "//<-- Server::areaConnection(Area&)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return points ; -} - - - -/* Calcule la distance entre les points "p1" et "p2" en tenant compte de la topologie. - */ -float Server::distanceTopology(const Point &p1, const Point &p2) -{ -#ifdef DEBUG_T - cout << "//--> Server::distanceTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - map - zones1(inWhichAreas(p1)), - zones2(inWhichAreas(p2)) ; - - if (zones1.size() == 0 || zones2.size() == 0) // Si aucune zone ne contient p1 ou p2, - { -#ifdef DEBUG_2 - cout << "Aucune zone ne contient " << p1 << " (" << zones1.size() << " zones) ou " << p2 << " (" << zones2.size() << " zones)." << endl ; -#endif // DEBUG_2 - -#ifdef DEBUG_T - cout << "//<-- Server::distanceTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return -1 ; // on quitte. - } - - Area - z1(zones1.begin()->second), // Première zone d'appartenance du point p1. // FIXME : vérifier toutes les zones - z2(zones2.begin()->second) ; - vector connection ; - - - /* *** Cas de la même zone *** */ - - if (z1 == z2) // Si les points sont dans la même zone, - { -#ifdef DEBUG_2 - cout << p1 << " et " << p2 << " sont dans la même zone." << endl ; -#endif // DEBUG_2 - -#ifdef DEBUG_T - cout << "//<-- Server::distanceTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return p1.distance(p2) ; // la distance entre eux est la distance euclidienne. - } - - - /* *** Cas de deux zones voisines (connectées directement) *** */ - - if ((connection = areaConnection(z1, z2)).size() != 0) // Si les points sont dans deux zones voisines, - { // la distance entre eux est la distance euclidienne de chacun jusqu'au plus proche point de passage entre les deux zones. - -#ifdef DEBUG_2 - cout << p1 << " et " << p2 << " sont dans deux zones voisines." << endl ; -#endif // DEBUG_2 - - float dist = p1.distance(connection[0]) + p2.distance(connection[0]) ; - for (unsigned int i = 1 ; i < connection.size() ; i++) // Recherche du point de passage offrant la plus courte distance - { - float tmp_dist = p1.distance(connection[i]) + p2.distance(connection[i]) ; - if (tmp_dist < dist) - dist = tmp_dist ; - } - -#ifdef DEBUG_T - cout << "//<-- Server::distanceTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return dist ; - } - - - /* *** Les points sont dans des zones non-voisines *** */ - -#ifdef DEBUG_2 - cout << p1 << " et " << p2 << " sont dans des zones non-voisines." << endl ; -#endif // DEBUG_2 - - vector // Liste des points de passage appartenant respectivement à z1 et à z2. - wp_z1(areaConnection(z1)), - wp_z2(areaConnection(z2)) ; - int // Indices des points de passage dans la liste : - wp_z1_idx, - wp_z2_idx = -1 ; // z2 ne peut pas être utilisé non initialisé, contrairement à ce que dit GCC, car dans le cas où il n'est pas initialisé on quitte la fonction avant de l'utiliser (cf. "return -1" un peu plus bas); - - if (wp_z1.size() == 0 || wp_z2.size() == 0) // Si l'une des deux zones ne comporte aucun point de passage, - { -#ifdef DEBUG_T - cout << "//<-- Server::distanceTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return -1 ; // on quitte (ceci ne devrait jamais se produire). - } - - /* Première itération (voir explication de l'algorithme plus bas) */ - unsigned int i1, i2 ; - for (i1 = 0 ; i1 < wp_z1.size() ; i1++) // Recherche des premiers indices valides (où il existe un chemin entre les points de passage) - { - wp_z1_idx = pointIndex(waypoint_list, wp_z1[i1]) ; - for (i2 = 0 ; i2 < wp_z2.size() ; i2++) - { - wp_z2_idx = pointIndex(waypoint_list, wp_z2[i2]) ; - if (wp_z2_idx < 0) - continue ; - - if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, - break ; // on arrête le parcours. - } - if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, - break ; // on arrête le parcours. - } - - if (i1 >= wp_z1.size()) // Si on a parcouru tout le tableau sans trouver de chemin, - { -#ifdef DEBUG_T - cout << "//<-- Server::distanceTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return -1 ; // on quitte. - } - - float - dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[i2]), - tmp_dist ; - - for (unsigned int j = i2 + 1 ; j < wp_z2.size() ; j++) // Fin du parcours : - { - wp_z2_idx = pointIndex(waypoint_list, wp_z2[j]) ; - if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) - continue ; - tmp_dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; - if (tmp_dist < dist) - dist = tmp_dist ; - } - - /* Itérations suivantes */ - for (unsigned int i = i1 + 1 ; i < wp_z1.size() ; i++) - for (unsigned int j = 0 ; j < wp_z2.size() ; j++) - { - // Indice des points de passage wp_z1[i] et wp_z2[j] dans la liste des points de passage : - wp_z1_idx = pointIndex(waypoint_list, wp_z1[i]) ; - wp_z2_idx = pointIndex(waypoint_list, wp_z2[j]) ; - - if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) // S'il n'existe aucun chemin entre les deux points de passage - continue ; - - /* La distance entre p1 et p2 est égale à la somme de : - * - la distance entre p1 et le point de passage courant de z1 - * (distance cartésienne car ils appartiennent à la même zone), - * - la distance entre p2 et le point de passage courant de z2 (idem), - * - la distance entre les deux points de passages suscités, qui est - * donnée par la matrice des distances entre points de passage - * (waypoint_matrix). - * On conservera bien sûr la somme qui donne le chemin le plus court. - */ - tmp_dist = p1.distance(wp_z1[i]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; - if (tmp_dist < dist) - dist = tmp_dist ; - } - -#ifdef DEBUG_T - cout << "//<-- Server::distanceTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return dist ; -} - - - -/* FONCTION POUR RÉTRO-COMPATIBILITÉ. - * Recherche un point de coordonnées (x;y;z) dans la liste reference_point_list, retourne true s'il existe, false sinon. */ -inline bool Server::pointExists(const float &x, const float &y, const float &z) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointExists(&float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - bool ret = pointExists(reference_point_list, Point(x, y, z)) ; - -#ifdef DEBUG_T - cout << "//<-- Server::pointExists(&float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -/* FONCTION POUR RÉTRO-COMPATIBILITÉ. - * Recherche un Point dans la liste reference_point_list, retourne true s'il existe, false sinon. */ -inline bool Server::pointExists(const Point &p) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointExists(&Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - bool ret = pointExists(reference_point_list, p) ; - -#ifdef DEBUG_T - cout << "//<-- Server::pointExists(&Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -/* Recherche un point de coordonnées (x;y;z) dans la liste "point_list", retourne true s'il existe, false sinon. */ -inline bool Server::pointExists(const vector &point_list, const float &x, const float &y, const float &z) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointExists(&vector, &float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - bool ret = pointExists(point_list, Point(x, y, z)) ; - -#ifdef DEBUG_T - cout << "//<-- Server::pointExists(&vector, &float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -/* Recherche un Point dans la liste "point_list", retourne true s'il existe, false sinon. */ -inline bool Server::pointExists(const vector &point_list, const Point &p) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointExists(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - bool ret = (pointIndex(point_list, p) != -1) ; - -#ifdef DEBUG_T - cout << "//<-- Server::pointExists(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -inline int Server::pointIndex(const float &x, const float &y, const float &z) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointIndex(&float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int ret = pointIndex(reference_point_list, Point(x, y, z)) ; - -#ifdef DEBUG_T - cout << "//<-- Server::pointIndex(&float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -inline int Server::pointIndex(const Point &p) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointIndex(&Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int ret = pointIndex(reference_point_list, p) ; - -#ifdef DEBUG_T - cout << "//<-- Server::pointIndex(&Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -inline int Server::pointIndex(const vector &point_list, const float &x, const float &y, const float &z) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointIndex(&vector, &float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int ret = pointIndex(point_list, Point(x, y, z)) ; - -#ifdef DEBUG_T - cout << "//<-- Server::pointIndex(&vector, &float, &float, &float)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -inline int Server::pointIndex(const vector &point_list, const Point &p) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointIndex(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int i; - - for (i = 0 ; i < point_list.size() ; i++) - if (p == point_list[i].getCoordinates()) - { -#ifdef DEBUG_T - cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return i ; - } - -#ifdef DEBUG_T - cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return -1 ; // Point non trouvé - } - - - -/* Retourne la position du Point "p" dans le tableau à une dimension "point_tab" de taille "size", ou -1 en cas d'échec. */ -inline int Server::pointIndex(const Point *point_tab, unsigned int &size, const Point &p) const - { - for (unsigned int i = 0 ; i < size ; i++) - if (point_tab[i] == p) - return i ; - - return -1 ; - } - - - -/* Retourne la position du Point "p" dans le vector "point_list", ou -1 en cas d'échec. */ -inline int Server::pointIndex(const vector &point_list, const Point &p) const - { -#ifdef DEBUG_T - cout << "//--> Server::pointIndex(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - for (unsigned int i = 0 ; i < point_list.size() ; i++) - if (point_list[i] == p) - { -#ifdef DEBUG_T - cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return i ; - } - -#ifdef DEBUG_T - cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return -1 ; - } - - - -bool Server::apExists(const string &ap_addr)const - { -#ifdef DEBUG_T - cout << "//--> Server::apExists()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - string str; - - for (unsigned int i = 0 ; i < access_point_list.size() ; i++) - { - str = access_point_list[i].getApAddr() ; - const int length = str.length() ; - for (int j = 0 ; j < length ; ++j) - str[j] = std::tolower(str[j]) ; - if (str == ap_addr) - { -#ifdef DEBUG_T - cout << "//<-- Server::apExists()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return true ; - } - } - -#ifdef DEBUG_T - cout << "//<-- Server::apExists()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return false ; - } - - - -unsigned int Server::apIndex(const string &ap_addr)const - { -#ifdef DEBUG_T - cout << "//--> Server::apIndex()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int i; - string str; - - for (i = 0 ; i < access_point_list.size() ; i++) - { - str = access_point_list[i].getApAddr() ; - const int length = str.length() ; - for (int j = 0 ; j < length ; ++j) - str[j] = std::tolower(str[j]) ; - if (str == ap_addr) - { -#ifdef DEBUG_T - cout << "//<-- Server::apIndex()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return i; - } - } - -#ifdef DEBUG_T - cout << "//<-- Server::apIndex()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return 0; // Should never happen - } - - - -/* Selects the "k" closest points from the measurement "m", in the SS space. - * Returns an empty vector if no points are found, which should never happen. - */ -vector Server::getkClosestInSs(const vector &m, const unsigned int &k)const - { -#ifdef DEBUG_T - cout << "//--> Server::getkClosestInSs(&vector, &unsigned int)" << endl ; - cout << "//<-- Server::getkClosestInSs(&vector, &unsigned int)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return getkClosestInSs(m, k, NULL) ; - } - - - -/* Selects the "k" closest points from the measurement "m", in the SS space. - * If "point_ignored" is not NULL, the Point "*point_ignored" is ignored. - * Returns an empty vector if no points are found, which should never happen. - */ -vector Server::getkClosestInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const - { -#ifdef DEBUG_T - cout << "//--> Server::getkClosestInSs(&vector, &unsigned int, *Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int i, j, min_idx; - vector distances_vector; - vector points_vector; - Point tmp_pt; - float tmp_distance = 0, dist_max = 10000000, tmp_min; - - for (i = 0 ; i < reference_point_list.size() ; i++) - if (point_ignored == NULL || (reference_point_list[i].getCoordinates() != *point_ignored)) - { - tmp_distance = reference_point_list[i].getSsSquareDistance(m); -#ifdef DEBUG_2 - cout << tmp_distance << " " ; -#endif // DEBUG_2 - - /* if not k points, add it */ - if (distances_vector.size() < k) - { - distances_vector.push_back(tmp_distance); - points_vector.push_back(reference_point_list[i].getCoordinates()); - dist_max = (dist_max < tmp_distance) ? tmp_distance : dist_max; - } - else - { - /* if tmp_dst < dist_max, should add it and remove previous greatest dist. */ - if (dist_max > tmp_distance) - { - /* remove old max */ - for (j = 0 ; j < distances_vector.size() ; j++) - if (distances_vector[j] == dist_max) - { - distances_vector[j] = tmp_distance; - points_vector[j] = reference_point_list[i].getCoordinates(); - break; - } - /* Now seek the new max. distance */ - dist_max = distances_vector[0]; - for (j = 1 ; j < distances_vector.size() ; j++) - if (distances_vector[j] > dist_max) - dist_max = distances_vector[j]; - } - /* Else nothing needs to be done */ - } - } -#ifdef DEBUG_2 - cout << endl ; -#endif // DEBUG_2 - - /* Sorts the vector */ - for (i = 0 ; i < distances_vector.size() - 1 ; i++) - { - tmp_min = distances_vector[i]; - min_idx = i; - for (j = i+1 ; j < distances_vector.size() ; j++) - if (tmp_min > distances_vector[j]) - { - tmp_min = distances_vector[j]; - min_idx = j; - } - - if (min_idx != i) - { - /* Swap points */ - tmp_pt = points_vector[i]; - points_vector[i] = points_vector[min_idx]; - points_vector[min_idx] = tmp_pt; - - /* Swap distances */ - distances_vector[min_idx] = distances_vector[i]; - distances_vector[i] = tmp_min; - } - } - -#ifdef DEBUG - cout << "getkClosestInSs() : Points sélectionnés :" << endl ; - if (distances_vector.size() != points_vector.size()) - cout << "Erreur ! distances_vector.size()=" << distances_vector.size() << " != points_vector.size()=" << points_vector.size() << endl ; - else - for (i = 0 ; i < distances_vector.size() ; i++) - cout << distances_vector[i] << " : " << points_vector[i] << endl ; -#endif // DEBUG - -#ifdef DEBUG_T - cout << "//<-- Server::getkClosestInSs(&vector, &unsigned int, *Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return points_vector; - } - - - -Point Server::getkWeightedInSs(const vector &m, const unsigned int &k)const - { -#ifdef DEBUG_T - cout << "//--> Server::getkWeightedInSs(&vector, &unsigned int)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - Point ret = getkWeightedInSs(m, k, NULL) ; - -#ifdef DEBUG_T - cout << "//<-- Server::getkWeightedInSs(&vector, &unsigned int)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret ; - } - - - -/* If "point_ignored" is not NULL, the Point "*point_ignored" is ignored. - */ -Point Server::getkWeightedInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const - { -#ifdef DEBUG_T - cout << "//--> Server::getkWeightedInSs(&vector, &unsigned int, *Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int i, j; - vector distances_vector; - vector points_vector; - float tmp_distance = 0, dist_max = 10000000; - Point ret; - float total = 0, x = 0, y = 0, z = 0; - - for (i = 0 ; i < reference_point_list.size() ; i++) - if (point_ignored == NULL || (reference_point_list[i].getCoordinates() != *point_ignored)) - { - tmp_distance = reference_point_list[i].getSsSquareDistance(m); - /* if not k points, add it */ - if (distances_vector.size() < k) - { - distances_vector.push_back(tmp_distance); - points_vector.push_back(reference_point_list[i].getCoordinates()); - dist_max = (dist_max < tmp_distance) ? tmp_distance : dist_max; - } - else - { - /* if tmp_dst < dist_max, should add it and remove previous greatest dist. */ - if (dist_max > tmp_distance) - { - /* remove old max */ - for (j = 0 ; j < distances_vector.size() ; j++) - if (distances_vector[j] == dist_max) - { - dist_max = tmp_distance; - distances_vector.erase(distances_vector.begin() + j); - points_vector.erase(points_vector.begin() + j); - distances_vector.push_back(tmp_distance); - points_vector.push_back(reference_point_list[i].getCoordinates()); - break; - } - } - /* Else nothing needs to be done */ - } - } - for (i = 0 ; i < distances_vector.size() ; i++) - total += (1 / distances_vector[i]); - - for (i = 0 ; i < distances_vector.size() ; i++) - { - x += points_vector[i].getX() * (1 / distances_vector[i]) / total; - y += points_vector[i].getY() * (1 / distances_vector[i]) / total; - z += points_vector[i].getZ() * (1 / distances_vector[i]) / total; - } - - ret.setX(x); - ret.setY(y); - ret.setZ(z); - -#ifdef DEBUG_T - cout << "//<-- Server::getkWeightedInSs(&vector, &unsigned int, *Point)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return ret; - } - - - -Point Server::kPointsAverage(const vector &vp)const - { -#ifdef DEBUG_T - cout << "//--> Server::kPointsAverage()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - unsigned int i; - float x=0, y=0, z=0; - Point p; - - for (i = 0 ; i < vp.size() ; i++) - { - x += vp[i].getX(); - y += vp[i].getY(); - z += vp[i].getZ(); - } - p.setX(x / (float) vp.size()); - p.setY(y / (float) vp.size()); - p.setZ(z / (float) vp.size()); - -#ifdef DEBUG_T - cout << "//<-- Server::kPointsAverage()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return p; - } - - - -Point Server::fbcm(const vector &m, const int &client_idx)const - { -#ifdef DEBUG_T - cout << "//--> Server::fbcm()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - Point ret(0, 0, 0); - vector addr; - vector dist_vect; - vector centres; - unsigned int i, ap_idx; - float constant_term, minmax_res, minmax_max; - float x = MINMAX_X_START, y = MINMAX_Y_START, z = MINMAX_Z_START; - - i = 0; - //cout << "FBCM: "; - for (i = 0 ; i < m.size() ; i++) - if (apExists(m[i].getMacAddr())) - { - ap_idx = apIndex(m[i].getMacAddr()); - //cout << "AP idx: " << ap_idx << " "; - centres.push_back(access_point_list[ap_idx].getCoordinates()); - addr.push_back(m[i].getMacAddr()); - constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain() + 2; - constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)); - //end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2. - //cout << "20log(" << (300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI) << ") = "; - //cout << constant_term << " "; - dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / (10 * access_point_list[ap_idx].getFriisIndex()))); - //cout << endl; - } - - /* Then: min-max */ - minmax_res = 1000000; - for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP) - for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP) - for (z = MINMAX_Z_START ; z <= MINMAX_Z_STOP ; z += MINMAX_STEP) - { - minmax_max = 0; - for (i = 0 ; i < centres.size() ; i++) - if (abs(centres[i].distance(x, y, z) - dist_vect[i]) > minmax_max) - minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; - if (minmax_max < minmax_res) - { - ret.setX(x); - ret.setY(y); - ret.setZ(z); - minmax_res = minmax_max; - } - } - - /* Clear all vectors */ - addr.clear(); - dist_vect.clear(); - centres.clear(); - -#ifdef DEBUG_T - cout << "//<-- Server::fbcm()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - /* Return position */ - return ret; - } - -/*second version of fbcm with as parameter vector &m and a list of friis index*/ -Point Server::fbcm_friis( const vector &m, const vector friis_idx_list, const float &z)const - { -#ifdef DEBUG_T - cout << "//--> Server::fbcm_friis()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - Point ret(0, 0, 0); - //vector addr; - vector dist_vect; - vector centres; - unsigned int i, j, ap_idx; - float constant_term, minmax_res, minmax_max; - float x = MINMAX_X_START, y = MINMAX_Y_START ; - vector vm = m; //Used when filtering 3 strongest APs - vector friis_idx = friis_idx_list; //Used when filtering 3 strongest APs - - i = 0; - //cout << "FBCM: "; - cout << "Received " << vm.size() << " measurements." << endl; - for (i = 0 ; i < vm.size() ; i++) - { - if (apExists(vm[i].getMacAddr())) - { - ap_idx = apIndex(vm[i].getMacAddr()); - cout << "AP " << vm[i].getMacAddr() << " was found at position " << ap_idx << endl; - constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain() + 2; - constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)); - if (friis_idx[i] != -1) - { - centres.push_back(access_point_list[ap_idx].getCoordinates()); - dist_vect.push_back(pow(10, (constant_term - vm[i].getAverage()) / (10 * friis_idx[i]))); - } - } - } - cout << "Computed " << dist_vect.size() << " Friis indexes. Values:" << endl; - for (j = 0 ; j < dist_vect.size() ; j++) - cout << "dist_vect du point d'accés: " << centres[j] << "--->>>" << dist_vect[j] < minmax_max) - minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; - if (minmax_max < minmax_res) - { - ret.setX(x); - ret.setY(y); - ret.setZ(z); - minmax_res = minmax_max; - } - } - - /* Clear all vectors */ - // addr.clear(); - dist_vect.clear(); - centres.clear(); - //cout << "RESULTAT DU FRBHM ---> " << ret << endl ; - -#ifdef DEBUG_T - cout << "//<-- Server::fbcm_friis()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - /* Return position */ - return ret; - } - - -Point Server::interlink(const vector &m, const int &client_idx)const - { -#ifdef DEBUG_T - cout << "//--> Server::interlink()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - Point ret(0, 0, 0); - vector addr; - vector dist_vect; - vector centres; - unsigned int i, ap_idx; - float constant_term, minmax_res, minmax_max; - float x = MINMAX_X_START, y = MINMAX_Y_START, z = MINMAX_Z_START; - - i = 0; - for (i = 0 ; i < m.size() ; i++) - if (apExists(m[i].getMacAddr())) - { - ap_idx = apIndex(m[i].getMacAddr()); - centres.push_back(access_point_list[ap_idx].getCoordinates()); - addr.push_back(m[i].getMacAddr()); - constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain(); - constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)) + 2; - //end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2. - dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / 35)); - } - - /* Then: min-max */ - minmax_res = 1000000; - for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP) - for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP) - for (z = MINMAX_Z_START ; z < MINMAX_Z_STOP ; z += MINMAX_STEP) - { - minmax_max = 0; - for (i = 0 ; i < centres.size() ; i++) - if (abs(centres[i].distance(x, y, z) - dist_vect[i]) > minmax_max) - minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; - if (minmax_max < minmax_res) - { - ret.setX(x); - ret.setY(y); - ret.setZ(z); - minmax_res = minmax_max; - } - } - - /* Clear all vectors */ - addr.clear(); - dist_vect.clear(); - centres.clear(); - -#ifdef DEBUG_T - cout << "//<-- Server::interlink()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - /* Return position */ - return ret; - } - - - -/* FONCTION POUR RÉTRO-COMPATIBILITÉ. - * Crée la liste des points de référence dans la liste reference_point_list. - */ -void Server::makeReferencePointListFromFile(const string &filename) -{ -#ifdef DEBUG_T - cout << "//--> Server::makePointListFromFile(&string)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - makePointListFromFile(reference_point_list, filename, true) ; - -#ifdef DEBUG_T - cout << "//<-- Server::makePointListFromFile(&string)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -void Server::makePointListFromFile(vector &dest_point_list, const string &filename) -{ -#ifdef DEBUG_T - cout << "//--> Server::makePointListFromFile(&vector, &string)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - makePointListFromFile(dest_point_list, filename, true) ; - -#ifdef DEBUG_T - cout << "//<-- Server::makePointListFromFile(&vector, &string)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -/* Lit le fichier de mesures (CSV) nommé "filename", et place les informations dans la liste "dest_point_list". - * Si "uniq_point" est vrai, on vérifiera l'existence d'un point avant tout ajout d'information, de manière à ne pas créer de doublon : si le point existe déjà, les informations lui seront ajoutées, sinon un nouveau point sera créé dans la liste. - * Si "uniq_point" est faux, un nouveau point sera créé pour chaque ligne du fichier. - */ -void Server::makePointListFromFile(vector &dest_point_list, const string &filename, const bool uniq_point) -{ -#ifdef DEBUG_T - cout << "//--> Server::makePointListFromFile(&vector, &string, bool)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - ifstream input_file ; // Flux d'entrée du fichier. - char buffer[BUFFER_LENGTH]; // Buffer lu dans le fichier. - string cpp_buffer ; // Buffer au format string. - ReferencePoint rp; - Point tmp_point; - float x, y, z ; // Coordonnées des points. - unsigned int pt_idx = 0 ; // Position du point lu dans la liste. - vector infos ; // Liste des informations lues dans une ligne du fichier. - - input_file.open(filename.c_str()) ; - - if (input_file.fail()) - { - cerr << "Error opening input file « " << filename << " » !" << endl ; - return ; - } - -#ifdef DEBUG - cout << "Lecture du fichier « " << filename << " »..." ; - int nlines = 0 ; - int npoints = 0 ; -#endif // DEBUG - - while (!input_file.eof()) - { -#ifdef DEBUG - if (nlines % 100 == 0) - printf("\n%5d", nlines) ; - cout << '.' ; - nlines++ ; -#endif // DEBUG - - input_file.getline(buffer, BUFFER_LENGTH); - - if ((input_file.rdstate() & ifstream::eofbit) == 0) - { - /* Extract fields */ - cpp_buffer = buffer; - if (cpp_buffer.size() == 0) // Ignorer une ligne vide - continue ; - - infos = extractReferencePointInfoFromBuffer(cpp_buffer); - x = string2float(infos[0]); - y = string2float(infos[1]); -#ifdef FRED_CSV_FORMAT - z = DEFAULT_Z ; -#else // FRED_CSV_FORMAT - z = string2float(infos[2]) ; -#endif // FRED_CSV_FORMAT - - /* Set point coordinates */ - tmp_point.setX(x); - tmp_point.setY(y); - tmp_point.setZ(z); - - /* Use C++ string format */ - if (!uniq_point || !pointExists(dest_point_list, tmp_point)) // Si on ne veut pas de points unique, ou que le point n'existe pas encore, - { - rp.setCoordinates(tmp_point); - dest_point_list.push_back(rp) ; // on le crée. - pt_idx = dest_point_list.size() - 1 ; // Le point que l'on vient d'ajouter est le dernier du vector. -#ifdef DEBUG - npoints++ ; -#endif // DEBUG -#ifdef DEBUG_2 - cout << tmp_point << " : ajouté." << endl ; -#endif // DEBUG_2 - } - else // Le point existe déjà : - { -#ifdef DEBUG_2 - cout << tmp_point << " : existe déjà." << endl ; -#endif // DEBUG_2 - pt_idx = pointIndex(dest_point_list, tmp_point) ; // On recherche le point auquel on veut ajouter les informations. - } - -#ifdef FRED_CSV_FORMAT - vector measures_vector = extractValues(infos[4]) ; - for (unsigned int i = 0 ; i < measures_vector.size() ; i++) - dest_point_list[pt_idx].addMeasurement(infos[3], measures_vector[i]); - measures_vector.clear(); -#else // FRED_CSV_FORMAT - for (unsigned int i = 4 ; i < infos.size() ; i++) - { -#ifdef DEBUG_2 - cout << "Lecture de la valeur : " << infos[i] << "... " ; -#endif // DEBUG_2 - if (i + 1 < infos.size()) - { - dest_point_list[pt_idx].addMeasurement(infos[i], string2int(infos[i+1])) ; -#ifdef DEBUG_2 - cout << "Mesure ajoutée : AP = " << infos[i] << " | SS = " << string2int(infos[i+1]) << endl ; -#endif // DEBUG_2 - i++ ; - } - } -#endif // FRED_CSV_FORMAT - } - } - -#ifdef DEBUG - cout << '\n' << nlines << " lignes lues, " << npoints << " points différents ajoutés.\n" << endl ; -#endif // DEBUG - - input_file.close(); - infos.clear() ; - -#ifdef DEBUG_T - cout << "//<-- Server::makePointListFromFile(&vector, &string, bool)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -void Server::makeApListFromFile(const string &filename) -{ -#ifdef DEBUG_T - cout << "//--> Server::makeApListFromFile()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - ifstream input_file; - char buffer[BUFFER_LENGTH]; - vector ap_infos; - AccessPoint tmp_ap; - - input_file.open(filename.c_str()); - if (input_file.fail()) - { - cerr << "Error opening input file « " << filename << " » !" << endl ; - return ; - } - -#ifdef DEBUG - cout << "Lecture du fichier « " << filename << " »..." << endl ; -#endif // DEBUG - - while (!input_file.eof()) - { - input_file.getline(buffer, BUFFER_LENGTH); - - if ((input_file.rdstate() & ifstream::eofbit) == 0) - { - /* Traitement basique des commentaires */ - if (buffer[0] == '\0' // Ligne vide - || buffer[0] == '#') // ou ligne commençant par # - continue ; // ignorer cette ligne. - - ap_infos = explode(buffer, ';'); -#ifdef DEBUG - cout << "AP : " << buffer ; -#endif // DEBUG - tmp_ap.setApAddr(ap_infos[0]); - tmp_ap.setCoordinates(string2float(ap_infos[1]), string2float(ap_infos[2]), string2float(ap_infos[3])); - tmp_ap.setFrequency(string2uint(ap_infos[4])); - tmp_ap.setAntennaGain(string2float(ap_infos[5])); - tmp_ap.setOutputPower(string2float(ap_infos[6])); - access_point_list.push_back(tmp_ap); - ap_infos.clear(); -#ifdef DEBUG - cout << " ajouté." << endl ; -#endif // DEBUG - } - } - -#ifdef DEBUG - cout << endl ; -#endif // DEBUG - - - input_file.close(); - -#ifdef DEBUG_T - cout << "//<-- Server::makeApListFromFile()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -/* Lit la liste des zones homogènes du bâtiment (pièces) dans le fichier "filename", et place le résultat dans "area_list". */ -void Server::makeTopologyFromFile(const string &filename) -{ -#ifdef DEBUG_T - cout << "//--> Server::makeTopologyFromFile()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - ifstream input_file ; - char buffer[BUFFER_LENGTH] ; - vector infos ; - - input_file.open(filename.c_str()) ; - if (input_file.fail()) - { - cerr << "Error opening input file « " << filename << " » !" << endl ; - return ; - } - -#ifdef DEBUG - cout << "Lecture du fichier « " << filename << " »..." << endl ; -#endif // DEBUG - - while (!input_file.eof()) - { - input_file.getline(buffer, BUFFER_LENGTH) ; - - if ((input_file.rdstate() & ifstream::eofbit) == 0) - { - /* Traitement basique des commentaires */ - if (buffer[0] == '\0' // Ligne vide - || buffer[0] == '#') // ou ligne commençant par # - continue ; // ignorer cette ligne. - - infos = explode(buffer, ';') ; -#ifdef DEBUG - cout << "Pièce : " << buffer ; -#endif // DEBUG - if (area_list.find(infos[0]) != area_list.end()) // Si la pièce existe déjà, - cerr << "Erreur ! Déclaration multiple de la zone « " << infos[0] << " »." << endl ; // on le signale ; - else // sinon on l'ajoute : - { - area_list[infos[0]] = Area(infos[0], string2float(infos[1]), string2float(infos[3]), string2float(infos[2]), string2float(infos[4]), string2float(infos[5]), string2float(infos[6])) ; -#ifdef DEBUG - cout << " ajoutée." << endl ; -#endif // DEBUG - } - - infos.clear() ; - } - } - -#ifdef DEBUG - cout << "--> Liste des pièces (" << area_list.size() << ") :" << endl ; - for (map::iterator it = area_list.begin() ; it != area_list.end() ; it++) - cout << it->first << " : " << it->second << endl ; - cout << endl ; -#endif // DEBUG - - input_file.close() ; - -#ifdef DEBUG_T - cout << "//<-- Server::makeTopologyFromFile()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -/* Lit la liste des points de passage dans le fichier "filename" et calcule les distances entre eux. Initialise waypoint_list et waypoint_matrix. - * TODO : tenir compte de la topologie pour les distances entre points. - */ -void Server::makeWaypointListFromFile(const string &filename) -{ -#ifdef DEBUG_T - cout << "//--> Server::makeWaypointListFromFile()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - - /* *** Lecture du fichier *** */ - - ifstream input_file ; - char buffer[BUFFER_LENGTH] ; - vector infos ; - set point_list ; - - input_file.open(filename.c_str()); - if (input_file.fail()) - { - cerr << "Error opening input file « " << filename << " » !" << endl ; -#ifdef DEBUG_T - cout << "//<-- Server::makeWaypointListFromFile()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return ; - } - -#ifdef DEBUG - cout << "Lecture du fichier « " << filename << " »..." << endl ; -#endif // DEBUG - - while (!input_file.eof()) - { - input_file.getline(buffer, BUFFER_LENGTH) ; - - if ((input_file.rdstate() & ifstream::eofbit) == 0) - { - /* Traitement basique des commentaires */ - if (buffer[0] == '\0' // Ligne vide - || buffer[0] == '#') // ou ligne commençant par # - continue ; // ignorer cette ligne. - - infos = explode(buffer, ';') ; -#ifdef DEBUG - cout << "Point de passage : " << buffer << ' ' ; - fflush(stdout); -#endif // DEBUG - - /* Ajout du point lu */ - Point tmp_pt(string2float(infos[0]), string2float(infos[1]), string2float(infos[2])) ; - if (! point_list.insert(tmp_pt).second) - cerr << "Point " << tmp_pt << " non ajouté ! Peut-être est-il dupliqué ?" << endl ; -#ifdef DEBUG - else - cout << "traité." << endl ; - fflush(stdout); -#endif // DEBUG - - infos.clear() ; - } - } - - input_file.close() ; // Lecture du fichier terminée - - - /* *** Construction de la matrice des distances *** */ - - unsigned int nb_pts = point_list.size() ; // Nombre de points - unsigned int cur_idx = 0 ; // Itérateur sur l'indice de la matrice. - waypoint_list.reserve(nb_pts) ; // Vector contenant tous les points (attribut du serveur) - waypoint_matrix = new float*[nb_pts] ; // Matrice (carrée) des distances entre les points de passage (attribut du serveur) - for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : - { - waypoint_matrix[i] = new float[nb_pts] ; - for (unsigned int k = 0 ; k < nb_pts ; k++) // Initialisation des distances à -1 - waypoint_matrix[i][k] = -1 ; - } - -#ifdef DEBUG - cout << "Traitement des points de passage (" << nb_pts << ")..." ; -#endif // DEBUG -#ifdef DEBUG_2 - cout << "--> Liste des points de passage (" << nb_pts << ") :" << endl ; - fflush(stdout); -#endif // DEBUG_2 - - - /* Initialisation (voisinage de premier ordre de chaque point */ - for (set::iterator it = point_list.begin() ; it != point_list.end() ; it++, cur_idx++) // Pour chaque point enregistré - { -#ifdef DEBUG - if (cur_idx % 100 == 0) - printf("\n%5d", cur_idx) ; - cout << '.' ; - fflush(stdout) ; -#endif // DEBUG -#ifdef DEBUG_2 - cout << *it << " :" ; -#endif // DEBUG_2 - - waypoint_list.push_back(*it) ; // Ajout du point dans waypoint_list - waypoint_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle - - for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent - { -#ifdef DEBUG_2 - cout << " / " << waypoint_list[k] ; -#endif // DEBUG_2 - if (inTheSameArea(waypoint_list[cur_idx], waypoint_list[k])) // Si le point est dans la même zone, - { - float dist = it->distance(waypoint_list[k]) ; // on calcule la distance - waypoint_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, - waypoint_matrix[k][cur_idx] = dist ; // dans les deux sens. - } - } - -#ifdef DEBUG_2 - cout << " /" << endl ; -#endif // DEBUG_2 - } - -#ifdef DEBUG - cout << endl ; -#endif // DEBUG - -#ifdef DEBUG_2 - /* Premier affichage de la matrice */ - cout << "--> Matrice des distances entre points de passage (après initialisation) :\n\t\t|" ; - for (unsigned int k = 0 ; k < nb_pts ; k++) - cout << ' ' << waypoint_list[k] << "\t|" ; - cout << endl ; - for (unsigned int k = 0 ; k < nb_pts ; k++) - { - cout << waypoint_list[k] << "\t|" ; - for (unsigned int l = 0 ; l < nb_pts ; l++) - cout << '\t' << waypoint_matrix[k][l] << "\t|" ; - cout << endl ; - } - cout << endl ; -#endif // DEBUG_2 - - - /* Itérations suivantes */ - bool comput_done = true ; - while (comput_done) - { - comput_done = false ; - - for (unsigned int i = 0 ; i < nb_pts ; i++) - for (unsigned int j = 0 ; j < nb_pts ; j++) - if (waypoint_matrix[i][j] > 0) - for (unsigned int k = 0 ; k < nb_pts ; k++) - if (waypoint_matrix[j][k] > 0) - { - /* /!\ - * NE PAS OPTIMISER (g++ -O0) ! - * Avec l'option d'optimisation de GCC (-O1, -O2 ou -O3), le test : - * (tmp_dist < round_float_2(waypoint_matrix[i][k]) || waypoint_matrix[i][k] == -1) - * est vrai, même si les deux comparaisons sont fausses. - * Cela semble provenir de la variable tmp_dist. - */ - float tmp_dist = round_float_2(waypoint_matrix[j][k] + waypoint_matrix[i][j]) ; - if (tmp_dist < round_float_2(waypoint_matrix[i][k]) || waypoint_matrix[i][k] == -1) - { - waypoint_matrix[i][k] = tmp_dist ; - comput_done = true ; - } - } - } - - -#ifdef DEBUG_2 - /* Deuxième affichage de la matrice */ - cout << "--> Matrice des distances entre points de passage :\n\t\t|" ; - for (unsigned int k = 0 ; k < nb_pts ; k++) - cout << ' ' << waypoint_list[k] << "\t|" ; - cout << endl ; - for (unsigned int k = 0 ; k < nb_pts ; k++) - { - cout << waypoint_list[k] << "\t|" ; - for (unsigned int l = 0 ; l < nb_pts ; l++) - cout << '\t' << waypoint_matrix[k][l] << "\t|" ; - cout << endl ; - } - cout << endl ; -#endif // DEBUG_2 - - -#ifdef DEBUG_T - cout << "//<-- Server::makeWaypointListFromFile()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -/* Vérifie la cohérence de la topologie décrite dans les fichiers de configuration. - * Retourne false si un problème est détecté, true sinon. - * /!\ La liste des *points de passage*, leur *matrice de distances*, ainsi que la liste des *points de référence*, DOIVENT ÊTRE INITIALISÉES avant l'appel à cette fonction. Il faut donc appeler makeWaypointListFromFile() et makeReferencePointListFromFile() avant checkTopology(). - */ -bool Server::checkTopology() -{ -#ifdef DEBUG_T - cout << "//--> Server::checkTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - bool ret = true ; - - - /* *** Recherche de points de passage n'appartenant à aucune zone *** */ - - for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) - { - map areas(inWhichAreas(waypoint_list[i])) ; - if (areas.empty()) - { -#ifdef DEBUG - cout << "Le point de passage " << waypoint_list[i] << " n'appartient à aucune zone !" << endl ; -#endif // DEBUG - - ret = false ; - } - -#ifdef DEBUG_2 - else - { - cout << "Le point de passage " << waypoint_list[i] << " appartient aux zones suivantes :" << endl ; - for (map::iterator it = areas.begin() ; it != areas.end() ; it++) - cout << '\t' << it->first << endl ; - } -#endif // DEBUG_2 - } - - - /* *** Recherche de points de référence n'appartenant à aucune zone *** */ - - for (unsigned int i = 0 ; i < reference_point_list.size() ; i++) - { - map areas(inWhichAreas((Point) reference_point_list[i])) ; - if (areas.empty()) - { -#ifdef DEBUG - cout << "Le point de référence " << (Point) reference_point_list[i] << " n'appartient à aucune zone !" << endl ; -#endif // DEBUG - - ret = false ; // À modifier si on veut permettre aux points de référence de n'appartenir à aucune zone. - } - -#ifdef DEBUG_2 - else - { - cout << "Le point de référence " << (Point) reference_point_list[i] << " appartient aux zones suivantes :" << endl ; - for (map::iterator it = areas.begin() ; it != areas.end() ; it++) - cout << '\t' << it->first << endl ; - } -#endif // DEBUG_2 - } - - - /* *** Recherche des pièces non connectées (et liste des connexions entre pièces) *** */ - - set connected_areas ; // Liste des zones connectées à au moins une autre zone (on n'enregistre que le nom des zones, dupliquer toutes les zones étant inutile). - - for (map::iterator it1 = area_list.begin() ; it1 != area_list.end() ; it1++) - for (map::iterator it2 = area_list.begin() ; it2 != area_list.end() ; it2++) - { - if (it1 == it2) - continue ; - - vector connect(areaConnection(it1->second, it2->second)) ; - - if (!connect.empty()) - { - connected_areas.insert(it1->first) ; // Ajout de la zone à la liste des zones connectées. - -#ifdef DEBUG - cout << "Les zones « " << it1->first << " » et « " << it2->first << " » sont connectées par les points suivants :" << endl ; - for (unsigned int i = 0 ; i < connect.size() ; i++) - cout << '\t' << connect[i] << endl ; -#endif // DEBUG - } -#ifdef DEBUG_2 - else - cout << "Les zones « " << it1->first << " » et « " << it2->first << " » ne sont pas connectées." << endl ; -#endif // DEBUG_2 - } - - if (connected_areas.size() != area_list.size()) - { -#ifdef DEBUG - map orphan_areas(area_list) ; // Liste des zones orphelines (non-connectées). Copie de la liste des zones (on devrait utiliser un set ne contenant que les noms, comme pour "connected_areas", mais c'est plus compliqué à coder alors on ne va pas s'embêter, surtout pour un affichage de débogage). - - for (set::iterator it = connected_areas.begin() ; it != connected_areas.end() ; it++) - orphan_areas.erase(*it) ; // On supprime chaque zone connectée de la liste des zones orphelines. - - cout << "Les zones suivantes ne sont connectées à aucune autre :" << endl ; - for (map::iterator it = orphan_areas.begin() ; it != orphan_areas.end() ; it++) - cout << '\t' << it->first << endl ; -#endif // DEBUG - - ret = false ; - } - - -#ifdef DEBUG_T - cout << "//<-- Server::checkTopology()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T + sprintf(ret, "%02x:%02x:%02x:%02x:%02x:%02x", mac_binary[0], mac_binary[1], mac_binary[2], mac_binary[3], mac_binary[4], mac_binary[5]) ; + ret[17] = '\0' ; return ret ; } - - -/* Calcule la distance entre tous les points de référence en tenant compte de la topologie (initialise reference_point_matrix). - * /!\ La liste des *points de passage*, leur *matrice de distances*, ainsi que la liste des *points de référence*, DOIVENT ÊTRE INITIALISÉES avant l'appel à cette fonction. Il faut donc appeler makeWaypointListFromFile() et makeReferencePointListFromFile() avant makeReferencePointDistances(). - */ -void Server::makeReferencePointDistances() +Server::Server(int port) { -#ifdef DEBUG_T - cout << "//--> Server::makeReferencePointDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - unsigned int nb_pts = reference_point_list.size() ; // Nombre de points à traiter. + listen_port = port; + client_len = sizeof(client); - /* Construction de la matrice des distances */ - reference_point_matrix = new float*[nb_pts] ; // Allocation de la première dimension. - for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : + /* Création d'une socket UDP */ + listen_socket = socket(AF_INET, SOCK_DGRAM, 0) ; + if (listen_socket < 0) { - reference_point_matrix[i] = new float[nb_pts] ; - for (unsigned int k = 0 ; k < nb_pts ; k++) // Initialisation des distances à -1 - reference_point_matrix[i][k] = -1 ; + cerr << "Échec de la création de la socket " << endl; + exit(1); } -#ifdef DEBUG - cout << "Traitement des points de référence (" << nb_pts << ")..." ; -#endif // DEBUG -#ifdef DEBUG_2 - cout << "--> Liste des points de référence (" << nb_pts << ") :" << endl ; - fflush(stdout); -#endif // DEBUG_2 + /* Remise à zéro et initialisation de la structure du serveur */ + bzero((char *) &serv_addr, sizeof(serv_addr)) ; // RÀZ + serv_addr.sin_family = AF_INET ; // Socket INET + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY) ; // Toutes les connexions sont acceptées + serv_addr.sin_port = htons(listen_port) ; // Port d'écoute - /* Calcul des distances */ - for (unsigned int cur_idx = 0 ; cur_idx < nb_pts ; cur_idx++) + /* Réservation du port */ + if (bind(listen_socket, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) { -#ifdef DEBUG - if (cur_idx % 100 == 0) - printf("\n%5d", cur_idx) ; - cout << '.' ; - fflush(stdout) ; -#endif // DEBUG -#ifdef DEBUG_2 - cout << (Point) reference_point_list[cur_idx] ; - cout << " :" ; -#endif // DEBUG_2 - - reference_point_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle - - for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent - { -#ifdef DEBUG_2 - cout << " / " << (Point) reference_point_list[k] ; -#endif // DEBUG_2 - - float dist = distanceTopology((Point) reference_point_list[cur_idx], (Point) reference_point_list[k]) ; // On calcule la distance - reference_point_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, - reference_point_matrix[k][cur_idx] = dist ; // dans les deux sens. - } - -#ifdef DEBUG_2 - cout << " /" << endl ; -#endif // DEBUG_2 + cerr << "Impossible de créer la socket (bind) " << endl; + close(listen_socket) ; + exit(1); } - -#ifdef DEBUG - cout << endl ; -#endif // DEBUG - -#ifdef DEBUG_2 - /* Affichage de la matrice */ - cout << "--> Matrice des distances entre points de référence :\n\t\t|" ; - for (unsigned int k = 0 ; k < nb_pts ; k++) - cout << ' ' << (Point) reference_point_list[k] << "\t|" ; - cout << endl ; - for (unsigned int k = 0 ; k < nb_pts ; k++) - { - cout << (Point) reference_point_list[k] << "\t|" ; - for (unsigned int l = 0 ; l < nb_pts ; l++) - cout << '\t' << reference_point_matrix[k][l] << "\t|" ; - cout << endl ; - } - - cout << endl ; -#endif // DEBUG_2 - -#ifdef DEBUG_T - cout << "//<-- Server::makeReferencePointDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T } - - -/* Place dans "matrix" les distances entre les points de "l1" et de "l2", en les cherchant dans "reference_point_matrix". - */ -void Server::selectDistances(float_array *matrix, const vector &l1, const vector &l2) const - { -#ifdef DEBUG_T - cout << "//--> Server::selectDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - matrix->resize(boost::extents[l1.size()][l2.size()]) ; - - for (unsigned int i = 0 ; i < l1.size() ; i++) - for (unsigned int j = 0 ; j < l2.size() ; j++) - (*matrix)[i][j] = reference_point_matrix[pointIndex(l1[i])][pointIndex(l2[j])] ; - -#ifdef DEBUG_T - cout << "//<-- Server::selectDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - } - - - -/* Calcule et place dans "matrix" les distances euclidiennes entre les points de "l1" et de "l2". - */ -void Server::computeEuclideanDistances(float_array *matrix, const vector &l1, const vector &l2) const - { -#ifdef DEBUG_T - cout << "//--> Server::computeEuclideanDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - matrix->resize(boost::extents[l1.size()][l2.size()]) ; - - for (unsigned int i = 0 ; i < l1.size() ; i++) - for (unsigned int j = 0 ; j < l2.size() ; j++) - (*matrix)[i][j] = l1[i].distance(l2[j]) ; - -#ifdef DEBUG_T - cout << "//<-- Server::computeEuclideanDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - } - - - -/* Calcule et place dans "matrix" les distances euclidiennes entre les points de "l1" et de "l2". - */ -void Server::computeTopologyDistances(float_array *matrix, const vector &l1, const vector &l2) +int Server::initFile(const string &apfile, const string &ptfile, const string &topofile, const string &wayfile) { -#ifdef DEBUG_T - cout << "//--> Server::computeTopologyDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T + calcul.makeTopologyFromFile(topofile.c_str()); + calcul.makeWaypointListFromFile(wayfile.c_str()); + calcul.makeReferencePointListFromFile(ptfile.c_str(), true); - matrix->resize(boost::extents[l1.size()][l2.size()]) ; - - for (unsigned int i = 0 ; i < l1.size() ; i++) - for (unsigned int j = 0 ; j < l2.size() ; j++) - (*matrix)[i][j] = distanceTopology(l1[i], l2[j]) ; - -#ifdef DEBUG_2 - cout << "computeTopologyDistances() : matrice calculée (" << l1.size() << "×" << l2.size() << ") :" << endl ; - for (unsigned int i = 0 ; i < l1.size() ; i++) + if (!calcul.checkTopology()) { - for (unsigned int j = 0 ; j < l2.size() ; j++) - cout << '[' << (*matrix)[i][j] << ']' ; - cout << endl ; - } -#endif // DEBUG_2 - -#ifdef DEBUG_T - cout << "//<-- Server::computeTopologyDistances()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -/* FONCTION POUR RÉTRO-COMPATIBILITÉ - * Affiche la liste des points de référence (reference_point_list). */ -void Server::printReferencePointList() -{ -#ifdef DEBUG_T - cout << "//--> Server::printReferencePointList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - printPointList(reference_point_list) ; - -#ifdef DEBUG_T - cout << "//<-- Server::printReferencePointList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -/* Affiche une liste de points (point_list). */ -void Server::printPointList(vector &point_list) -{ -#ifdef DEBUG_T - cout << "//--> Server::printPointList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - for (unsigned int i = 0 ; i < point_list.size() ; i++) - cout << point_list[i] << endl ; - -#ifdef DEBUG_T - cout << "//<-- Server::printPointList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T -} - - - -void Server::printAccessPointList() const - { -#ifdef DEBUG_T - cout << "//--> Server::printAccessPointList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - for (unsigned int i = 0 ; i < access_point_list.size() ; i++) - cout << access_point_list[i] << endl; - -#ifdef DEBUG_T - cout << "//<-- Server::printAccessPointList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - } - - - -void Server::computeFriisFromRefList() -{ -#ifdef DEBUG_T - cout << "//--> Server::computeFriisFromRefList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - vector friis_idx_list; - Point pt_coords, ap_coords; - float ap_power, ap_gain, calib_gain = 2, const_term, mes_power, friis_sum; - unsigned int ap_freq; - string ap_mac; - - for (unsigned int i = 0 ; i < access_point_list.size() ; i++) - { - ap_power = access_point_list[i].getOutputPower(); - ap_coords = access_point_list[i].getCoordinates(); - ap_freq = access_point_list[i].getFrequency(); - ap_gain = access_point_list[i].getAntennaGain(); - ap_mac = access_point_list[i].getApAddr(); - - /* Compute main general term, independant from scans */ - const_term = calib_gain + ap_gain; - const_term -= 20 * log10(4 * M_PI); - const_term += 20 * log10 (300000000.0 / ap_freq) + ap_power; - - /* Compute an index for each ref point. List stored in friis_idx_list */ - for (unsigned int j = 0 ; j < reference_point_list.size() ; j++) - { - pt_coords = reference_point_list[j].getCoordinates(); - if (reference_point_list[i].getPowerForAp(ap_mac, &mes_power)) - friis_idx_list.push_back((const_term - mes_power) / (10 * log10(ap_coords.distance(pt_coords)))); - } - - /* Now, compute avg value */ - friis_sum = 0; - for (unsigned int j = 0 ; j < friis_idx_list.size() ; j++) - friis_sum += friis_idx_list[j]; - access_point_list[i].setFriisIndex(friis_sum / friis_idx_list.size()); - - cout << access_point_list[i].getApAddr() << " -> " << (friis_sum / friis_idx_list.size()) << endl; - - friis_idx_list.clear(); + cerr << "Erreur lors de la création de la topology" << endl; + exit(1); } -#ifdef DEBUG_T - cout << "//<-- Server::computeFriisFromRefList()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T + calcul.makeReferencePointDistances(); + calcul.makeApListFromFile(apfile.c_str()); + + return 0; } - - -/*Deuxième version de computeFriisFromRefList qui prend en entrée un point et retourne la liste d'index de friis équivalent*/ -vector Server::computeFriisFromRefList(const Point &p, const vector &m) +int Server::start() { -#ifdef DEBUG_T - cout << "//--> Server::computeFriisFromRefList(&Point, &vector)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - vector friis_idx_list; - Point pt_coords, ap_coords; - float ap_power, ap_gain, calib_gain = 2, const_term, mes_power/*, friis_sum*/; - unsigned int ap_freq; - string ap_mac; + cout << "Serveur prêt" << endl; - - for (unsigned int i = 0 ; i < access_point_list.size() ; i++) - { - cout << "La distance entre le point d'accès: " << access_point_list[i].getCoordinates()<< "et le point -->" << p.distance(access_point_list[i].getCoordinates()) << endl; - } - - /* Compute an index for each ref point. List stored in friis_idx_list */ - /* Compute an index for Point p. List stored in friis_idx_list */ - for (unsigned int j = 0 ; j < reference_point_list.size() ; j++) - { - pt_coords = reference_point_list[j].getCoordinates(); - if (pt_coords==p) - { - for (unsigned int i = 0 ; i < m.size() ; i++) - { - if (apExists(m[i].getMacAddr())) - { - unsigned int ap_idx = apIndex(m[i].getMacAddr()); - ap_power = access_point_list[ap_idx].getOutputPower(); - ap_coords = access_point_list[ap_idx].getCoordinates(); - ap_freq = access_point_list[ap_idx].getFrequency(); - ap_gain = access_point_list[ap_idx].getAntennaGain(); - ap_mac = access_point_list[ap_idx].getApAddr(); - - /* Compute main general term, independant from scans */ - const_term = calib_gain + ap_gain; - const_term -= 20 * log10(4 * M_PI); - const_term += 20 * log10 (300000000.0 / ap_freq) + ap_power; - - if (reference_point_list[j].getPowerForAp(ap_mac, &mes_power)) - friis_idx_list.push_back((const_term - mes_power) / (10 * log10(ap_coords.distance(pt_coords)))); - else - friis_idx_list.push_back(-1); - cout << "AP " << m[i].getMacAddr() << " has Friis index: " << friis_idx_list[i] << endl; - } - } - break; - } - } - -#ifdef DEBUG_T - cout << "//<-- Server::computeFriisFromRefList(&Point, &vector)" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return friis_idx_list; -} - - - -/* Ajoute un client (ClientInfo) à la liste "client_list", et renvoie une référence sur l'élément ajouté. */ -ClientInfo& Server::createClient() -{ -#ifdef DEBUG_T - cout << "//--> Server::createClient()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - client_list.push_back(ClientInfo()) ; - -#ifdef DEBUG_T - cout << "//<-- Server::createClient()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return client_list.back() ; -} - - - -/* Localise le client d'identifiant "client_id" en appliquant l'algorithme voulu. */ -void Server::monitorClient(const unsigned int &client_id, const ALGORITHM &algo) -{ -#ifdef DEBUG_T - cout << "//--> Server::monitorClient()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - if (VITERBI_N < 2) - { - cerr << "monitorClient() : N ne peut être inférieur à 2 !" << endl ; -#ifdef DEBUG_T - cout << "//<-- Server::monitorClient()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - return ; - } - - vector - &E_current = client_list[client_id].getRef_viterbi_Ecurrent(), - &E_previous = client_list[client_id].getRef_viterbi_Eprevious() ; - Point position ; - float_array dst_matrix ; - vector friisFromList; - Point pointFastViterbi; - Point Frbhmbasique; - string filename = "trajet.txt"; - ofstream fichier; - -#ifdef TEST - vector peregrination_point_list ; - makePointListFromFile(peregrination_point_list, DEFAULT_TRACKING_FILE, false) ; -#endif // TEST - - -#ifdef DEBUG - cout << reference_point_list.size() << " points de référence" ; -#ifdef TEST - cout << ", " << peregrination_point_list.size() << " points de pérégrination." << endl ; -#else // TEST - cout << '.' << endl ; -#endif // TEST -#endif // DEBUG -#ifdef DEBUG_2 - cout << "***** Liste des points de référence : *****" << endl ; - printReferencePointList() ; -#ifdef TEST - cout << "***** Liste des points de pérégrination : *****" << endl ; - printPointList(peregrination_point_list) ; -#endif // TEST - cout << "*********************************" << endl ; -#endif // DEBUG_2 - -#ifdef TEST - unsigned int pt = 0 ; - while (pt < peregrination_point_list.size()) -#else // TEST + /* Récupération des données envoyées par le client */ while (true) -#endif // TEST { - vector vm ; - -#ifdef TEST - /* Get point measurements */ - //vm.clear(); - vm = peregrination_point_list[pt].getMeasurementList(); -#else // TEST - vm = récupère_mesure() ; // FIXME ! -#endif // TEST - - E_previous = E_current ; - E_current = getkClosestInSs(vm, VITERBI_K) ; // Création de l'ensemble des K points les plus proches dans l'espace des puissances. - -#ifdef DEBUG - cout << "Point courant : " << peregrination_point_list[pt] ; -#endif // DEBUG - - switch (algo) + if (recvfrom(listen_socket, &att_request, sizeof(att_request), 0, (struct sockaddr *) &client, &client_len) < 0) { - case ALGO_VLI : /* Application de l'algorithme Viterbi */ - computeEuclideanDistances(&dst_matrix, E_previous, E_current) ; // On précalcule les distances entre les points de E_previous et E_current. - position = fastViterbiLike(client_id, dst_matrix) ; - break ; - - case ALGO_BASIC_FRBHM : /* Application de l'algorithme FRBHM basique */ - cout << "-------FRBHM BASIQUE---------" << endl ; - //computeFriisFromRefList() ; - selectDistances(&dst_matrix, E_previous, E_current) ; // On récupère une sous-matrice de reference_point_matrix avec les distances entre les points de E_previous et E_current. - position = fastViterbiLike(client_id, dst_matrix) ; - cout << "Position: " << position << endl; - friisFromList = computeFriisFromRefList(position, vm) ; - //fbcm_friis(vm, friisFromList) ; - //Just to see - cout << "---------------------------" << endl; - for (unsigned int i = 0 ; i < access_point_list.size() ; i ++) - cout << "Dist between ap " << access_point_list[i].getCoordinates() << " and true point = " << access_point_list[i].getCoordinates().distance(peregrination_point_list[pt].getCoordinates()) << endl; - //end of 'just to see' - Frbhmbasique = fbcm_friis(vm, friisFromList, position.getZ()); - cout << "Point selectionné final: " << Frbhmbasique << endl; - fichier.open(filename.c_str(), std::ios::app); - if ( !fichier ) - { - cerr << "Erreur de creation du fichier" << endl; - exit(1); - } - fichier << Frbhmbasique << std::endl; - fichier.close(); - break ; - - case ALGO_CONTINU_FRBHM : /* Application de l'algorithme FRBHM continu */ - cout << "--------FRBHM CONTINU------------" << endl ; - //computeFriisFromRefList(); - - //Just to see - cout << "---------------------------" << endl; - for (unsigned int i = 0 ; i < access_point_list.size() ; i ++) - cout << "Dist between ap " << access_point_list[i].getCoordinates() << " and true point " << peregrination_point_list[pt].getCoordinates() << " = " << access_point_list[i].getCoordinates().distance(peregrination_point_list[pt].getCoordinates()) << endl; - //end of 'just to see' - - for (unsigned int i = 0 ; i < E_current.size() ; i++) - { - friisFromList = computeFriisFromRefList(E_current[i], vm) ; - E_current[i] = fbcm_friis(vm, friisFromList,E_current[i].getZ()) ; - } - computeTopologyDistances(&dst_matrix, E_previous, E_current) ; // On calcule les distances entre les points de E_previous et E_current, en tenant compte de la topologie). - pointFastViterbi = fastViterbiLike(client_id, dst_matrix) ; - fichier.open(filename.c_str(), std::ios::app); - cout << "Point selectionné: " << pointFastViterbi << endl; - if ( !fichier ) - { - cerr << "Erreur de creation du fichier" << endl; - exit(1); - } - fichier << pointFastViterbi << endl; - fichier.close(); - break; - - default : - cerr << "Erreur ! Algorithme inconnu." << endl ; + cerr << "Aucun message reçu du client" << endl; + close(listen_socket); + return 1; } -#ifdef TEST - pt++ ; -#endif // TEST - } + recv_info.resize(att_request.nb_couples); -#ifdef DEBUG_T - cout << "//<-- Server::monitorClient()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T + for (int i = 0; i < att_request.nb_couples; i++) + recvfrom(listen_socket, &recv_info.at(i), sizeof(couple_info), 0, (struct sockaddr *) &client, &client_len); + + treatment(att_request, recv_info); + recv_info.clear(); + } } - - -/* - * Computes new cumulative distances for the viterbi instance of the client nb "client_id". - * Returns the solution (Point) of the last ended viterbi. - * Distances are grouped by line corresponding to an instance. - */ -Point Server::fastViterbiLike(const unsigned int &client_id, const float_array &distance_matrix) +void Server::treatment(request att_request, vector recv_info) { -#ifdef DEBUG_T - cout << "//--> Server::fastViterbiLike()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - float_array &V = client_list[client_id].getRef_viterbi_V() ; - vector &E_current = client_list[client_id].getRef_viterbi_Ecurrent() ; - unsigned int &i = client_list[client_id].getRef_viterbi_iteration() ; + Treatment treat(calcul.getAccessPointList(), calcul.getReferencePointList()); + Point solution; - int N = VITERBI_N, K = VITERBI_K ; + makeMeasurementList(recv_info); - unsigned int V0_min_k = 0 ; // Indice du point sélectionné à chaque itération + /* Interlink Networks */ + solution = treat.interlink(point_list, 0) ; + cout << "Interlink Networks : "<< solution << endl; + /* RADAR */ + solution = treat.getkClosestInSs(point_list, 1, NULL)[0] ; + cout << "RADAR : " << solution << endl; - if (i > 1) // Si on n'est plus à la première itération + /* FBCM */ + solution = treat.fbcm(point_list, 0) ; + cout << "FBCM : " << solution << endl; + + /* 1-NSS + FBCM */ + solution = treat.getkClosestInSs(point_list, 1, NULL)[0] ; + solution = treat.fbcm_friis(point_list, treat.computeFriisFromRefList(solution, point_list), solution.getZ()) ; + cout << "1-NSS + FBCM : " << solution << endl; + + /* 2-NSS */ + solution = treat.getkWeightedInSs(point_list, 2, NULL); + cout << "2-NSS : " << solution << endl; + + /* 3-NSS */ + solution = treat.getkWeightedInSs(point_list, 3, NULL); + cout << "3-NSS : " << solution << endl; + + /* 5-NSS */ + solution = treat.getkWeightedInSs(point_list, 5, NULL); + cout << "5-NSS : " << solution << endl; + + cout << endl ; + + point_list.clear(); +} + +void Server::makeMeasurementList(vector recv_info) +{ + + Measurement m; + bool inserted = false; + + for (unsigned int i = 0; i < recv_info.size(); i++) { - /* Recalcul des plus courtes distances */ - for (float_index n = N-1-i ; n < N-2 ; n++) // Pour chaque historique existant (sauf le dernier), - for (float_index k = 0 ; k < K ; k++) // pour chaque point de l'historique, - { // on met à jour le chemin minimum entre l'historique précédent et le point : - V[n][k] = V[n+1][0] + distance_matrix[0][k] ; - for (float_index l = 1 ; l < K ; l++) - { - float f = V[n+1][l] + distance_matrix[l][k] ; - if (f < V[n][k]) - V[n][k] = f ; - } + + string mac_a = mac_bytes_to_string(recv_info.at(i).ap_mac_addr_bytes); + int value = recv_info.at(i).antenna_signal_dbm; + + for (unsigned int j = 0 ; j < point_list.size() ; j++) + if (point_list[j].getMacAddr() == mac_a) + { + point_list[j].addSsValue(value); + inserted = true; + break; } - - /* Traitement du dernier historique */ - for (float_index k = 0 ; k < K ; k++) // Pour chaque point, - { // on récupère le chemin minimum entre l'historique précédent et le point : - V[N-2][k] = distance_matrix[0][k] ; - for (float_index l = 1 ; l < K ; l++) - { - float f = distance_matrix[l][k] ; - if (f < V[N-2][k]) - V[N-2][k] = f ; - } - } - - /* Choix du point à renvoyer */ - V0_min_k = 0 ; // Indice du point correspondant au V0 minimal. Si le tableau n'est pas plein, la plus petite valeur a l'indice 0 (car getkClosestInSs() renvoit un résultat trié). - if (N-1-i == 0) + if (inserted == false) { -#ifdef DEBUG - float V0_min = V[0][0] ; - cout << "V[0][0]=" << V[0][0] << " ; V0_min=" << V0_min << " ; V0_min_k=" << V0_min_k << " -- " ; -#endif // DEBUG - for (float_index k=1 ; k < K ; k++) - { - if (V[0][k] < V0_min) - { - V0_min_k = k ; -#ifdef DEBUG - V0_min = V[0][k] ; -#endif // DEBUG - } -#ifdef DEBUG - cout << "V[0][" << k << "]=" << V[0][k] << " ; V0_min=" << V0_min << " ; V0_min_k=" << V0_min_k << " -- " ; -#endif // DEBUG - } -#ifdef DEBUG - cout << "V0_min = " << V0_min << " ; V0_min_k=" << V0_min_k << endl ; -#endif // DEBUG + m.setMacAddr(mac_a); + m.addSsValue(value); + point_list.push_back(m); } } - -#ifdef DEBUG - cout << "V :" << endl ; - for (float_index n=0 ; n < N-1 ; n++) - { - for (float_index k=0 ; k < K ; k++) - cout << "[" << V[n][k] << "]" ; - cout << endl ; - } - cout << "Point sélectionné : " << E_current[V0_min_k] << endl ; - cout << "--------------------------" << endl ; -#endif // DEBUG - - if (i < N-1) - i++ ; - -#ifdef DEBUG_T - cout << "//<-- Server::fastViterbiLike()" << endl ; - fflush(stdout) ; -#endif // DEBUG_T - - return E_current[V0_min_k] ; -} - - - -/* For experimentation purpose only */ -void Server::radar_exp(const string &outfile, const string &testfile) -{ - string fname; - ofstream logfile; - Point solution, solution_kw, ref_coords; - unsigned int i; - vector vm; - - computeFriisFromRefList() ; - - if (client_list.empty()) - { -#ifdef DEBUG - cout << "radar_exp() : création d'un client." << endl ; -#endif // DEBUG - createClient() ; - } - - logfile.open(outfile.c_str()); - if (logfile.fail()) - { - cerr << "Error opening output file « " << logfile << " » !" << endl ; - return ; - } - - /* Column names */ - logfile << "Coordinates\ -\tInterlink\t(Error)\ -\tRADAR\t(Error)\ -\tFBCM\t(Error)\ -\tFRBHM\t(Error)" << endl ; - - cout << reference_point_list.size() << " reference points." << endl ; - - vector test_point_list ; - makePointListFromFile(test_point_list, DEFAULT_REF_POINT_FILE_1M, true) ; - cout << test_point_list.size() << " reference points to test." << endl ; - float radar_error = 0, in_error = 0, fbcm_error = 0, frbhm_error = 0; - - for (i = 0 ; i < test_point_list.size() ; i++) - { - /* Get point measurements */ - vm = test_point_list[i].getMeasurementList(); - cout << vm.size() << " measurements:" << endl ; - for (unsigned int prout = 0 ; prout < vm.size() ; prout++) - cout << vm[prout] << endl; - ref_coords = test_point_list[i].getCoordinates(); - - /* Print point coordinates */ - logfile << ref_coords << "\t"; - - /* Interlink Networks */ - solution = interlink(vm, 0) ; - logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; - in_error += solution.distance(ref_coords); - - /* RADAR */ - solution = getkClosestInSs(vm, 1, &ref_coords)[0] ; - logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; - radar_error += solution.distance(ref_coords); - - /* FBCM */ - solution = fbcm(vm, 0) ; - logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; - fbcm_error += solution.distance(ref_coords); - - /* 1-NSS + FBCM */ - solution = getkClosestInSs(vm, 1, &ref_coords)[0] ; - solution = fbcm_friis(vm, computeFriisFromRefList(solution, vm), solution.getZ()) ; - logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; - frbhm_error += solution.distance(ref_coords); - -// /* 2-NSS */ -// solution = getkWeightedInSs(vm, 2, &ref_coords); -// logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; - -// /* 3-NSS */ -// solution = getkWeightedInSs(vm, 3, &ref_coords); -// logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; - -// /* 5-NSS */ -// solution = getkWeightedInSs(vm, 5, &ref_coords); -// logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; - - logfile << endl ; - vm.clear() ; - } - /* Mean values formulas names */ - float nb = (float) test_point_list.size(); - logfile << "\t\t" << (in_error / nb) << "\t\t" << (radar_error / nb) << "\t\t" << (fbcm_error / nb) << "\t\t" << (frbhm_error / nb) << endl ; - logfile.close(); } diff --git a/owlps-positioning/server.hh b/owlps-positioning/server.hh index e7e9a6b..ad927d8 100644 --- a/owlps-positioning/server.hh +++ b/owlps-positioning/server.hh @@ -1,149 +1,65 @@ #ifndef _SERVER_HH_ #define _SERVER_HH_ -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include -#include -#include +#include +#include +#include + +#include +#include + +#include #include -#include "guinumo.hh" -#include "clientinfo.hh" -#include "referencepoint.hh" -#include "accesspoint.hh" +#include "positioning.hh" #include "point.hh" #include "measurement.hh" -#include "area.hh" +#include "treatment.hh" using namespace std; -typedef ClientInfo::float_array float_array ; -typedef ClientInfo::float_index float_index ; - - -#define DEFAULT_LOGFILE "log/radar_exp.csv" // Fichier de sortie -#define DEFAULT_REF_POINT_FILE "csv/agreg/1m/toutes.csv" // Fichier des points de référence -#define DEFAULT_REF_POINT_FILE_1M "csv/agreg/1m/toutes.csv" // Fichier contenant tous les points de référence (maillage à 1m) -#define DEFAULT_AP_FILE "cfg/minipc.cfg" // Fichier de configuration des AP -#define DEFAULT_TRACKING_FILE "csv/agreg/divagation/divagation9_interpolé.csv" // Fichier de prérégrination -#define DEFAULT_TOPOLOGY_FILE "cfg/topo.csv" -#define DEFAULT_WAYPOINT_FILE "cfg/waypoints.csv" -#define DEFAULT_IP "127.0.0.1" -#define DEFAULT_LISTEN_PORT 7777 -#define LIGHT_SPEED 300000000 -#define MINMAX_STEP 0.5 -#define MINMAX_X_START 0.5 -#define MINMAX_Y_START 0.5 -#define MINMAX_Z_START 0 -#define MINMAX_X_STOP 10 -#define MINMAX_Y_STOP 31.5 -#define MINMAX_Z_STOP 6 -#define BUFFER_LENGTH 5000 -//#define DEFAULT_Z 3 // Décommenter pour utiliser des fichiers d'entrée avec des coordonnées dans un seul plan (X, Y). -//#define FRED_CSV_FORMAT // Décommenter pour utiliser les fichiers CSV au « format Fred » (plusieurs lignes par mesure, avec un AP par ligne). - -typedef enum { ALGO_VLI = 1, ALGO_BASIC_FRBHM, ALGO_CONTINU_FRBHM } ALGORITHM ; +typedef struct _couple_info + { + unsigned char ap_mac_addr_bytes[6]; // Adresse MAC de l'AP + int antenna_signal_dbm; // Puissance du signal reçu par l'AP + } couple_info; +typedef struct _request + { + unsigned char ag_mac_addr_bytes[6]; // Adresse MAC de l'Aggregateur émetteur de la demande + int nb_couples; // Nombre couples (MAC AP;Puissance) + } request; class Server { - public : - typedef boost::multi_array float_array ; // On utilise boost::multi_array pour les matrices de distances temporaires. - typedef float_array::index float_index ; - protected: - vector client_list ; // Liste des clients connus. - map area_list ; // Liste des zones homogènes (pièces). - vector reference_point_list ; // Liste des points de référence (calibration). - vector access_point_list ; // Liste des AP connus. - float **reference_point_matrix ; // Matrice des distances entre les points de référence. - vector waypoint_list ; // Liste des points de passage entre les zones. - float **waypoint_matrix ; // Matrice des distances entre les points de passage. - struct sockaddr_in server_addr; - int sockListen; - int sockSend; + private: + request att_request; + vector recv_info; + + int listen_socket; + int listen_port; + struct sockaddr_in serv_addr; + struct sockaddr_in client; + socklen_t client_len; + + Positioning calcul; + vector point_list; public: - Server(const string &ap_file = DEFAULT_AP_FILE, const string &ref_pt_file = DEFAULT_REF_POINT_FILE, const string &ip_addr = DEFAULT_IP, const int &listen_port = DEFAULT_LISTEN_PORT); - ~Server(); + Server(int); + ~Server() + { + close(listen_socket); + }; - void send_to_client(const int &cl); - int receive_data(); - - ClientInfo& createClient() ; - - map inWhichAreas(const Point &p) ; - bool inTheSameArea(const Point &p1, const Point &p2) ; - vector areaConnection(const Area &z1, const Area &z2) ; - vector areaConnection(const Area &z) ; - float distanceTopology(const Point &p1, const Point &p2) ; - - bool pointExists(const float &x, const float &y, const float &z)const; - bool pointExists(const Point &p)const; - bool pointExists(const vector &point_list, const float &x, const float &y, const float &z) const ; - bool pointExists(const vector &point_list, const Point &p) const ; - - int pointIndex(const float &x, const float &y, const float &z) const; - int pointIndex(const Point &p) const; - int pointIndex(const vector &point_list, const float &x, const float &y, const float &z) const ; - int pointIndex(const vector &point_list, const Point &p) const ; - int pointIndex(const Point *tab, unsigned int &size, const Point &p) const ; - int pointIndex(const vector &point_list, const Point &p) const ; - - bool apExists(const string &ap_addr)const; - unsigned int apIndex(const string &ap_addr)const; - - vector getkClosestInSs(const vector &m, const unsigned int &k)const ; - vector getkClosestInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const ; - - Point getkWeightedInSs(const vector &m, const unsigned int &k)const ; - Point getkWeightedInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const ; - - Point kPointsAverage(const vector &vp)const; - Point fbcm(const vector &m, const int &client_idx)const; - Point fbcm_friis( const vector &m, const vector friis_idx_list, const float &z)const; - Point interlink(const vector &m, const int &client_idx)const; - - void makeReferencePointListFromFile(const string &filename); - void makePointListFromFile(vector &dest_point_list, const string &filename) ; - void makePointListFromFile(vector &dest_point_list, const string &filename, const bool uniq_point) ; - void makeApListFromFile(const string &filename); - void makeTopologyFromFile(const string &filename) ; - void makeWaypointListFromFile(const string &filename) ; - void makeReferencePointDistances() ; - - bool checkTopology() ; - - void selectDistances(float_array *matrix, const vector &l1, const vector &l2) const ; - void computeEuclideanDistances(float_array *matrix, const vector &l1, const vector &l2) const ; - void computeTopologyDistances(float_array *matrix, const vector &l1, const vector &l2) ; - - void printReferencePointList() ; - void printPointList(vector &point_list) ; - void printAccessPointList() const ; - - void computeFriisFromRefList(); - vector computeFriisFromRefList(const Point &p, const vector &m); - - unsigned int getNbReferencePoints()const - { - return reference_point_list.size(); - }; - - void monitorClient(const unsigned int &client_id, const ALGORITHM &algo) ; - Point fastViterbiLike(const unsigned int &id_client, const float_array &distance_matrix) ; - - /* For experimentation purpose only ! */ - void radar_exp(const string &outfile = DEFAULT_LOGFILE, const string &testfile = DEFAULT_REF_POINT_FILE_1M); + int initFile(const string &, const string &, const string &, const string &); + int start(); + void treatment(request, vector); + void makeMeasurementList(vector); }; -#endif // _SERVER_HH_ +#endif diff --git a/owlps-positioning/treatment.cc b/owlps-positioning/treatment.cc new file mode 100644 index 0000000..085fb0f --- /dev/null +++ b/owlps-positioning/treatment.cc @@ -0,0 +1,382 @@ +#include "treatment.hh" + +bool Treatment::apExists(const string &ap_addr)const + { + + string str; + + for (unsigned int i = 0 ; i < access_point_list.size() ; i++) + { + str = access_point_list[i].getApAddr() ; + const int length = str.length() ; + for (int j = 0 ; j < length ; ++j) + str[j] = tolower(str[j]) ; + if (str == ap_addr) + { + return true ; + } + } + + return false ; + } + +unsigned int Treatment::apIndex(const string &ap_addr)const + { + unsigned int i; + string str; + + for (i = 0 ; i < access_point_list.size() ; i++) + { + str = access_point_list[i].getApAddr() ; + const int length = str.length() ; + for (int j = 0 ; j < length ; ++j) + str[j] = tolower(str[j]) ; + if (str == ap_addr) + { + return i; + } + } + + return 0; // Should never happen + } + +vector Treatment::getkClosestInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const + { + + unsigned int i, j, min_idx; + vector distances_vector; + vector points_vector; + Point tmp_pt; + float tmp_distance = 0, dist_max = 10000000, tmp_min; + + for (i = 0 ; i < reference_point_list.size() ; i++) + if (point_ignored == NULL || (reference_point_list[i].getCoordinates() != *point_ignored)) + { + tmp_distance = reference_point_list[i].getSsSquareDistance(m); + + /* if not k points, add it */ + if (distances_vector.size() < k) + { + distances_vector.push_back(tmp_distance); + points_vector.push_back(reference_point_list[i].getCoordinates()); + dist_max = (dist_max < tmp_distance) ? tmp_distance : dist_max; + } + else + { + /* if tmp_dst < dist_max, should add it and remove previous greatest dist. */ + if (dist_max > tmp_distance) + { + /* remove old max */ + for (j = 0 ; j < distances_vector.size() ; j++) + if (distances_vector[j] == dist_max) + { + distances_vector[j] = tmp_distance; + points_vector[j] = reference_point_list[i].getCoordinates(); + break; + } + /* Now seek the new max. distance */ + dist_max = distances_vector[0]; + for (j = 1 ; j < distances_vector.size() ; j++) + if (distances_vector[j] > dist_max) + dist_max = distances_vector[j]; + } + /* Else nothing needs to be done */ + } + } + + /* Sorts the vector */ + for (i = 0 ; i < distances_vector.size() - 1 ; i++) + { + tmp_min = distances_vector[i]; + min_idx = i; + for (j = i+1 ; j < distances_vector.size() ; j++) + if (tmp_min > distances_vector[j]) + { + tmp_min = distances_vector[j]; + min_idx = j; + } + + if (min_idx != i) + { + /* Swap points */ + tmp_pt = points_vector[i]; + points_vector[i] = points_vector[min_idx]; + points_vector[min_idx] = tmp_pt; + + /* Swap distances */ + distances_vector[min_idx] = distances_vector[i]; + distances_vector[i] = tmp_min; + } + } + + return points_vector; + } + +Point Treatment::fbcm(const vector &m, const int &client_idx)const + { + + Point ret(0, 0, 0); + vector addr; + vector dist_vect; + vector centres; + unsigned int i, ap_idx; + float constant_term, minmax_res, minmax_max; + float x = MINMAX_X_START, y = MINMAX_Y_START, z = MINMAX_Z_START; + + i = 0; + //cout << "FBCM: "; + for (i = 0 ; i < m.size() ; i++) + if (apExists(m[i].getMacAddr())) + { + ap_idx = apIndex(m[i].getMacAddr()); + //cout << "AP idx: " << ap_idx << " "; + centres.push_back(access_point_list[ap_idx].getCoordinates()); + addr.push_back(m[i].getMacAddr()); + constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain() + 2; + constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)); + //end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2. + //cout << "20log(" << (300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI) << ") = "; + //cout << constant_term << " "; + dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / (10 * access_point_list[ap_idx].getFriisIndex()))); + //cout << endl; + } + + /* Then: min-max */ + minmax_res = 1000000; + for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP) + for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP) + for (z = MINMAX_Z_START ; z <= MINMAX_Z_STOP ; z += MINMAX_STEP) + { + minmax_max = 0; + for (i = 0 ; i < centres.size() ; i++) + if (abs(centres[i].distance(x, y, z) - dist_vect[i]) > minmax_max) + minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; + if (minmax_max < minmax_res) + { + ret.setX(x); + ret.setY(y); + ret.setZ(z); + minmax_res = minmax_max; + } + } + + /* Clear all vectors */ + addr.clear(); + dist_vect.clear(); + centres.clear(); + + /* Return position */ + return ret; + } + +Point Treatment::fbcm_friis( const vector &m, const vector friis_idx_list, const float &z)const + { + + Point ret(0, 0, 0); + vector dist_vect; + vector centres; + unsigned int i, ap_idx; + float constant_term, minmax_res, minmax_max; + float x = MINMAX_X_START, y = MINMAX_Y_START ; + vector vm = m; //Used when filtering 3 strongest APs + vector friis_idx = friis_idx_list; //Used when filtering 3 strongest APs + + i = 0; + for (i = 0 ; i < vm.size() ; i++) + { + if (apExists(vm[i].getMacAddr())) + { + ap_idx = apIndex(vm[i].getMacAddr()); + constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain() + 2; + constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)); + if (friis_idx[i] != -1) + { + centres.push_back(access_point_list[ap_idx].getCoordinates()); + dist_vect.push_back(pow(10, (constant_term - vm[i].getAverage()) / (10 * friis_idx[i]))); + } + } + } + + + /* Then: min-max */ + minmax_res = 1000000; + for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP) + for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP) + { + minmax_max = 0; + for (i = 0 ; i < centres.size() ; i++) + if (abs(centres[i].distance(x, y, z) - dist_vect[i]) > minmax_max) + minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; + if (minmax_max < minmax_res) + { + ret.setX(x); + ret.setY(y); + ret.setZ(z); + minmax_res = minmax_max; + } + } + + /* Clear all vectors */ + dist_vect.clear(); + centres.clear(); + + /* Return position */ + return ret; + } + +Point Treatment::interlink(const vector &m, const int &client_idx) const + { + + Point ret(0, 0, 0); + vector addr; + vector dist_vect; + vector centres; + unsigned int i, ap_idx; + float constant_term, minmax_res, minmax_max; + float x = MINMAX_X_START, y = MINMAX_Y_START, z = MINMAX_Z_START; + + i = 0; + for (i = 0 ; i < m.size() ; i++) + if (apExists(m[i].getMacAddr())) + { + ap_idx = apIndex(m[i].getMacAddr()); + centres.push_back(access_point_list[ap_idx].getCoordinates()); + addr.push_back(m[i].getMacAddr()); + constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain(); + constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)) + 2; + //end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2. + dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / 35)); + } + + /* Then: min-max */ + minmax_res = 1000000; + for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP) + for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP) + for (z = MINMAX_Z_START ; z < MINMAX_Z_STOP ; z += MINMAX_STEP) + { + minmax_max = 0; + for (i = 0 ; i < centres.size() ; i++) + if (abs(centres[i].distance(x, y, z) - dist_vect[i]) > minmax_max) + minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]); + if (minmax_max < minmax_res) + { + ret.setX(x); + ret.setY(y); + ret.setZ(z); + minmax_res = minmax_max; + } + } + + /* Clear all vectors */ + addr.clear(); + dist_vect.clear(); + centres.clear(); + + /* Return position */ + return ret; + } + +vector Treatment::computeFriisFromRefList(const Point &p, const vector &m) +{ + + vector friis_idx_list; + Point pt_coords, ap_coords; + float ap_power, ap_gain, calib_gain = 2, const_term, mes_power/*, friis_sum*/; + unsigned int ap_freq; + string ap_mac; + + + /* Compute an index for each ref point. List stored in friis_idx_list */ + /* Compute an index for Point p. List stored in friis_idx_list */ + for (unsigned int j = 0 ; j < reference_point_list.size() ; j++) + { + pt_coords = reference_point_list[j].getCoordinates(); + if (pt_coords==p) + { + for (unsigned int i = 0 ; i < m.size() ; i++) + { + if (apExists(m[i].getMacAddr())) + { + unsigned int ap_idx = apIndex(m[i].getMacAddr()); + ap_power = access_point_list[ap_idx].getOutputPower(); + ap_coords = access_point_list[ap_idx].getCoordinates(); + ap_freq = access_point_list[ap_idx].getFrequency(); + ap_gain = access_point_list[ap_idx].getAntennaGain(); + ap_mac = access_point_list[ap_idx].getApAddr(); + + /* Compute main general term, independant from scans */ + const_term = calib_gain + ap_gain; + const_term -= 20 * log10(4 * M_PI); + const_term += 20 * log10 (300000000.0 / ap_freq) + ap_power; + + if (reference_point_list[j].getPowerForAp(ap_mac, &mes_power)) + friis_idx_list.push_back((const_term - mes_power) / (10 * log10(ap_coords.distance(pt_coords)))); + else + friis_idx_list.push_back(-1); + } + } + break; + } + } + + return friis_idx_list; +} + +Point Treatment::getkWeightedInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const + { + + unsigned int i, j; + vector distances_vector; + vector points_vector; + float tmp_distance = 0, dist_max = 10000000; + Point ret; + float total = 0, x = 0, y = 0, z = 0; + + for (i = 0 ; i < reference_point_list.size() ; i++) + if (point_ignored == NULL || (reference_point_list[i].getCoordinates() != *point_ignored)) + { + tmp_distance = reference_point_list[i].getSsSquareDistance(m); + /* if not k points, add it */ + if (distances_vector.size() < k) + { + distances_vector.push_back(tmp_distance); + points_vector.push_back(reference_point_list[i].getCoordinates()); + dist_max = (dist_max < tmp_distance) ? tmp_distance : dist_max; + } + else + { + /* if tmp_dst < dist_max, should add it and remove previous greatest dist. */ + if (dist_max > tmp_distance) + { + /* remove old max */ + for (j = 0 ; j < distances_vector.size() ; j++) + if (distances_vector[j] == dist_max) + { + dist_max = tmp_distance; + distances_vector.erase(distances_vector.begin() + j); + points_vector.erase(points_vector.begin() + j); + distances_vector.push_back(tmp_distance); + points_vector.push_back(reference_point_list[i].getCoordinates()); + break; + } + } + /* Else nothing needs to be done */ + } + } + for (i = 0 ; i < distances_vector.size() ; i++) + total += (1 / distances_vector[i]); + + for (i = 0 ; i < distances_vector.size() ; i++) + { + x += points_vector[i].getX() * (1 / distances_vector[i]) / total; + y += points_vector[i].getY() * (1 / distances_vector[i]) / total; + z += points_vector[i].getZ() * (1 / distances_vector[i]) / total; + } + + ret.setX(x); + ret.setY(y); + ret.setZ(z); + + return ret; + } + diff --git a/owlps-positioning/treatment.hh b/owlps-positioning/treatment.hh new file mode 100644 index 0000000..333940b --- /dev/null +++ b/owlps-positioning/treatment.hh @@ -0,0 +1,57 @@ +#ifndef _TREATMENT_HH_ +#define _TREATMENT_HH_ + +#include +#include +#include +#include + +#include "point.hh" +#include "measurement.hh" +#include "accesspoint.hh" +#include "referencepoint.hh" + +#define LIGHT_SPEED 300000000 +#define MINMAX_STEP 0.5 +#define MINMAX_X_START 0.5 +#define MINMAX_Y_START 0.5 +#define MINMAX_Z_START 0 +#define MINMAX_X_STOP 10 +#define MINMAX_Y_STOP 31.5 +#define MINMAX_Z_STOP 6 + +using namespace std; + +class Treatment + { + + private: + vector access_point_list; + vector reference_point_list; + + public: + Treatment(vector access_point, vector reference_point) + { + access_point_list = access_point; + reference_point_list = reference_point; + }; + ~Treatment() + { + access_point_list.clear(); + }; + + bool apExists(const string &)const; + unsigned int apIndex(const string &)const; + + vector getkClosestInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const; + + Point kPointsAverage(const vector &vp)const; + Point fbcm(const vector &m, const int &client_idx)const; + Point fbcm_friis( const vector &m, const vector friis_idx_list, const float &z)const; + Point interlink(const vector &m, const int &client_idx)const; + + vector computeFriisFromRefList(const Point &p, const vector &m); + Point getkWeightedInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const ; + }; + +#endif